/* * Copyright (c) 2013 ITOCHU Techno-Solutions Corporation. * * 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 jp.co.ctc_g.jse.core.message; import java.util.Map; import java.util.ResourceBundle; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import jp.co.ctc_g.jfw.core.internal.InternalException; import jp.co.ctc_g.jfw.core.internal.InternalMessages; import jp.co.ctc_g.jfw.core.util.Args; import jp.co.ctc_g.jfw.core.util.Arrays; import jp.co.ctc_g.jfw.core.util.Strings; import jp.co.ctc_g.jse.core.message.Messages.MessageType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.support.RequestContextUtils; /** * <p> * このクラスは、メッセージを保存するためのインタフェースを提供するコンテキストです。<br/> * </p> * @author ITOCHU Techno-Solutions Corporation. */ public class MessageContext { /** * <p> * メッセージを格納するためのスコープを表現する列挙型です。 * </p> * @author ITOCHU Techno-Solutions Corporation. */ public enum Scope { /** * リクエスト */ REQUEST, /** * フラッシュ */ FLASH, /** * セッション */ SESSION } /** {@code MessageContext} インスタンスを{@link HttpServletRequest}に保存する際のキー */ public static final String MESSAGE_CONTEXT_ATTRIBUTE_KEY = MessageContext.class.getName() + ".MESSAGE_CONTEXT"; /** 入力チェックエラー・メッセージを格納した{@link Messages}インスタンスを{@link HttpServletRequest}に保存する際のキー */ public static final String VALIDATION_MESSAGE_KEY_TO_REQUEST = MessageContext.class.getName() + ".VALIDATION_MESSAGE_KEY_TO_REQUEST"; /** 入力チェックエラー・メッセージを格納した{@link Messages}インスタンスをフラッシュ・スコープに保存する際のキー */ public static final String VALIDATION_MESSAGE_KEY_TO_FLASH = MessageContext.class.getName() + ".VALIDATION_MESSAGE_KEY_TO_FLASH"; /** エラー・メッセージを格納した{@link Messages}インスタンスを{@link HttpServletRequest}に保存する際のキー */ public static final String ERROR_MESSAGE_KEY_TO_REQUEST = MessageContext.class.getName() + ".ERROR_MESSAGE_KEY_TO_REQUEST"; /** エラー・メッセージを格納した{@link Messages}インスタンスをフラッシュ・スコープに保存する際のキー */ public static final String ERROR_MESSAGE_KEY_TO_FLASH = MessageContext.class.getName() + ".ERROR_MESSAGE_KEY_TO_FLASH"; /** エラー・メッセージを格納した{@link Messages}インスタンスをセッション・スコープに保存する際のキー */ public static final String ERROR_MESSAGE_KEY_TO_SESSION = MessageContext.class.getName() + ".ERROR_MESSAGE_KEY_TO_SESSION"; /** インフォメーション・メッセージを格納した{@link Messages}インスタンスを{@link HttpServletRequest}に保存する際のキー */ public static final String INFORMATION_MESSAGE_KEY_TO_REQUEST = MessageContext.class.getName() + ".INFORMATION_MESSAGE_KEY_TO_REQUEST"; /** インフォメーション・メッセージを格納した{@link Messages}インスタンスをフラッシュ・スコープに保存する際のキー */ public static final String INFORMATION_MESSAGE_KEY_TO_FLASH = MessageContext.class.getName() + ".INFORMATION_MESSAGE_KEY_TO_FLASH"; /** インフォメーション・メッセージを格納した{@link Messages}インスタンスをセッション・スコープに保存する際のキー */ public static final String INFORMATION_MESSAGE_KEY_TO_SESSION = MessageContext.class.getName() + "INFORMATION_MESSAGE_KEY_TO_SESSION"; /** 画面上に表示しないメッセージを格納するキー */ public static final String MESSGE_IGNORE_KEY = MessageContext.class.getName() + ".MESSAGE_IGNORE_KEY"; /** メッセージをスコープにバインドする際のキー文字列の配列 */ protected static final String[] MESSAGES_KEY; static { MESSAGES_KEY = Arrays.gen( VALIDATION_MESSAGE_KEY_TO_REQUEST, VALIDATION_MESSAGE_KEY_TO_FLASH, INFORMATION_MESSAGE_KEY_TO_REQUEST, INFORMATION_MESSAGE_KEY_TO_FLASH, INFORMATION_MESSAGE_KEY_TO_SESSION, ERROR_MESSAGE_KEY_TO_REQUEST, ERROR_MESSAGE_KEY_TO_FLASH, ERROR_MESSAGE_KEY_TO_SESSION ); } private HttpServletRequest request; private static final ResourceBundle R = InternalMessages.getBundle(MessageContext.class); private static final Logger L = LoggerFactory.getLogger(MessageContext.class); /** * デフォルトコンストラクタです。 */ public MessageContext() {} /** * コンストラクタです。 * @param request {@link HttpServletRequest} インスタンス */ public MessageContext(HttpServletRequest request) { Args.checkNotNull(request); this.request = request; } /** * <p> * バリデーションメッセージをリクエストスコープに保存します。<br/> * </p> * @param code メッセージを指定するキー * @param property プロパティ名 * @param constraintName バリデータ名 * @param modelName モデル名 */ public void saveValidationMessageToRequest(String code, String property, String constraintName, String modelName) { saveValidationMessageToRequest(code, null, property, constraintName, modelName); } /** * <p> * バリデーションメッセージを指定されたスコープに保存します。<br/> * </p> * @param code メッセージを指定するキー * @param property プロパティ名 * @param constraintName バリデータ名 * @param modelName モデル名 * @param scope 保存するスコープ */ public void saveValidationMessage(String code, String property, String constraintName, String modelName, Scope scope) { saveValidationMessage(code, null, property, constraintName, modelName, scope); } /** * <p> * バリデーションメッセージを指定されたスコープに保存します。<br/> * </p> * @param code メッセージを指定するキー * @param replace プレースホルダーを置換するキーと値の{@link Map} * @param property プロパティ名 * @param constraintName バリデータ名 * @param modelName モデル名 * @param scope 保存するスコープ */ public void saveValidationMessage(String code, Map<String, ? extends Object> replace, String property, String constraintName, String modelName, Scope scope) { Args.checkNotNull(scope); switch (scope) { case REQUEST: saveValidationMessageToRequest(code, replace, property, constraintName, modelName); break; case FLASH: saveValidationMessageToFlash(code, replace, property, constraintName, modelName); break; case SESSION: default: L.debug(R.getString("D-MESSAGE_CONTEXT#0001")); throw new InternalException(MessageContext.class, "D-MESSAGE_CONTEXT#0001"); } } /** * <p> * バリデーションメッセージをリクエストスコープに保存します。<br/> * </p> * @param code メッセージを指定するキー * @param replace プレースホルダーを置換するキーと値の{@link Map} * @param property プロパティ名 * @param constraintName バリデータ名 * @param modelName モデル名 */ public void saveValidationMessageToRequest( String code, Map<String, ? extends Object> replace, String property, String constraintName, String modelName) { Args.checkNotBlank(code); Messages messages = (Messages) request.getAttribute(VALIDATION_MESSAGE_KEY_TO_REQUEST); if (messages == null) messages = new Messages(MessageType.VALIDATION); messages.add(new Message(code, replace, property, constraintName, modelName)); request.setAttribute(VALIDATION_MESSAGE_KEY_TO_REQUEST, messages); } /** * 入力チェックエラー・メッセージをフラッシュスコープにストアします。 * @param code メッセージ・コード * @param property プロパティ名 * @param constraintName 入力チェック名 * @param modelName モデル名 */ public void saveValidationMessageToFlash(String code, String property, String constraintName, String modelName) { saveValidationMessageToFlash(code, null, property, constraintName, modelName); } /** * 入力チェックエラー・メッセージをフラッシュスコープにストアします。 * @param code メッセージ・コード * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} * @param property プロパティ名 * @param constraintName 入力チェック名 * @param modelName モデル名 */ public void saveValidationMessageToFlash( String code, Map<String, ? extends Object> replace, String property, String constraintName, String modelName) { Args.checkNotNull(code); Messages messages = (Messages)RequestContextUtils.getOutputFlashMap(request).get(VALIDATION_MESSAGE_KEY_TO_FLASH); if (messages == null) { messages = new Messages(MessageType.VALIDATION); } messages.add(new Message(code, replace, property, constraintName, modelName)); RequestContextUtils.getOutputFlashMap(request).put(VALIDATION_MESSAGE_KEY_TO_FLASH, messages); } /** * インフォメーション・メッセージをリクエスト・スコープにストアします。 * @param code メッセージ・コード */ public void saveInformationMessageToRequest(String code) { saveInformationMessageToRequest(code, null); } /** * インフォメーション・メッセージをリクエスト・スコープにストアします。 * @param code メッセージ・コード * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} */ public void saveInformationMessageToRequest( String code, Map<String, ? extends Object> replace) { Args.checkNotBlank(code); Messages messages = (Messages) request.getAttribute(INFORMATION_MESSAGE_KEY_TO_REQUEST); if (messages == null) messages = new Messages(MessageType.INFORMATION); messages.add(new Message(code, replace)); request.setAttribute(INFORMATION_MESSAGE_KEY_TO_REQUEST, messages); } /** * インフォメーション・メッセージをフラッシュ・スコープにストアします。 * @param code メッセージ・コード */ public void saveInformationMessageToFlash(String code) { saveInformationMessageToFlash(code, null); } /** * インフォメーション・メッセージをフラッシュ・スコープにストアします。 * @param code メッセージ・コード * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} */ public void saveInformationMessageToFlash( String code, Map<String, ? extends Object> replace) { Args.checkNotNull(code); Messages messages = (Messages)RequestContextUtils.getOutputFlashMap(request).get(INFORMATION_MESSAGE_KEY_TO_FLASH); if (messages == null) { messages = new Messages(MessageType.INFORMATION); RequestContextUtils.getOutputFlashMap(request).put(INFORMATION_MESSAGE_KEY_TO_FLASH, messages); } messages.add(new Message(code, replace)); } /** * インフォメーション・メッセージをセッション・スコープにストアします。 * @param code メッセージ・コード */ public void saveInformationMessageToSession(String code) { saveInformationMessageToSession(code, null); } /** * インフォメーション・メッセージをセッション・スコープにストアします。 * セッションが存在しない場合はセッションを開始します。 * @param code メッセージ・コード * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} */ public void saveInformationMessageToSession(String code, Map<String, ? extends Object> replace) { Args.checkNotBlank(code); HttpSession session = request.getSession(true); Messages messages = (Messages) session.getAttribute(INFORMATION_MESSAGE_KEY_TO_SESSION); if (messages == null) messages = new Messages(MessageType.INFORMATION); messages.add(new Message(code, replace)); session.setAttribute(INFORMATION_MESSAGE_KEY_TO_SESSION, messages); } /** * <p> * インフォメーション・メッセージを指定されたスコープに保存します。<br/> * </p> * @param code メッセージを指定するキー * @param scope 保存するスコープ */ public void saveInformationMessage(String code, Scope scope) { saveInformationMessage(code, null, scope); } /** * <p> * インフォメーション・メッセージを指定されたスコープに保存します。<br/> * </p> * @param code メッセージを指定するキー * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} * @param scope 保存するスコープ */ public void saveInformationMessage(String code, Map<String, ? extends Object> replace, Scope scope) { Args.checkNotNull(scope); switch (scope) { case FLASH: saveInformationMessageToFlash(code, replace); break; case SESSION: saveInformationMessageToSession(code, replace); break; case REQUEST: default: saveInformationMessageToRequest(code, replace); break; } } /** * <p> * エラー・メッセージを指定されたスコープに保存します。<br/> * </p> * @param code メッセージを指定するキー * @param scope 保存するスコープ */ public void saveErrorMessage(String code, Scope scope) { saveErrorMessage(code, null, scope); } /** * <p> * エラー・メッセージを指定されたスコープに保存します。<br/> * </p> * @param code メッセージを指定するキー * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} * @param scope 保存するスコープ */ public void saveErrorMessage(String code, Map<String, ? extends Object> replace, Scope scope) { Args.checkNotNull(scope); switch (scope) { case FLASH: saveErrorMessageToFlash(code, replace); break; case SESSION: saveErrorMessageToSession(code, replace); break; case REQUEST: default: saveErrorMessageToRequest(code, replace); break; } } /** * ストアされているインフォメーション・メッセージをクリアします。 */ public void clearInformationMessage() { MessageType type = MessageType.INFORMATION; clearForRequest(INFORMATION_MESSAGE_KEY_TO_REQUEST, null, type); clearForFlash(INFORMATION_MESSAGE_KEY_TO_FLASH, null, type); clearForSession(INFORMATION_MESSAGE_KEY_TO_SESSION, null, type); } /** * ストアされているインフォメーション・メッセージをクリアします。 * このメソッドは指定されたキーが格納されているスコープは関係なく、削除します。 * @param code メッセージを指定するキー */ public void clearInformationMessage(String code) { MessageType type = MessageType.INFORMATION; clearForRequest(INFORMATION_MESSAGE_KEY_TO_REQUEST, code, type); clearForFlash(INFORMATION_MESSAGE_KEY_TO_FLASH, code, type); clearForSession(INFORMATION_MESSAGE_KEY_TO_SESSION, code, type); } /** * エラー・メッセージをリクエスト・スコープにストアします。 * @param code メッセージ・コード */ public void saveErrorMessageToRequest(String code) { saveErrorMessageToRequest(code, null); } /** * エラー・メッセージをリクエスト・スコープにストアします。 * @param code メッセージ・コード * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} */ public void saveErrorMessageToRequest( String code, Map<String, ? extends Object> replace) { Args.checkNotBlank(code); Messages messages = (Messages)request.getAttribute(ERROR_MESSAGE_KEY_TO_REQUEST); if (messages == null) messages = new Messages(MessageType.ERROR); messages.add(new Message(code, replace)); request.setAttribute(ERROR_MESSAGE_KEY_TO_REQUEST, messages); } /** * エラー・メッセージをフラッシュ・スコープにストアします。 * @param code メッセージ・コード */ public void saveErrorMessageToFlash(String code) { saveErrorMessageToFlash(code, null); } /** * エラー・メッセージをフラッシュ・スコープにストアします。 * @param code メッセージ・コード * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} */ public void saveErrorMessageToFlash( String code, Map<String, ? extends Object> replace) { Args.checkNotBlank(code); Messages messages = (Messages)RequestContextUtils.getOutputFlashMap(request).get(ERROR_MESSAGE_KEY_TO_FLASH); if (messages == null) { messages = new Messages(MessageType.ERROR); RequestContextUtils.getOutputFlashMap(request).put(ERROR_MESSAGE_KEY_TO_FLASH, messages); } messages.add(new Message(code, replace)); } /** * エラー・メッセージをセッション・スコープにストアします。 * @param code メッセージ・コード */ public void saveErrorMessageToSession(String code) { saveErrorMessageToSession(code, null); } /** * エラー・メッセージをセッション・スコープにストアします。 * @param code メッセージ・コード * @param replace メッセージのプレースホルダを置換するキーとバリューの{@link Map} */ public void saveErrorMessageToSession(String code, Map<String, ? extends Object> replace) { Args.checkNotBlank(code); HttpSession session = request.getSession(true); Messages messages = (Messages)session.getAttribute(ERROR_MESSAGE_KEY_TO_SESSION); if (messages == null) messages = new Messages(MessageType.ERROR); messages.add(new Message(code, replace)); session.setAttribute(ERROR_MESSAGE_KEY_TO_SESSION, messages); } /** * ストアされているエラー・メッセージをクリアします。 */ public void clearErrorMessage() { MessageType type = MessageType.ERROR; clearForRequest(ERROR_MESSAGE_KEY_TO_REQUEST, null, type); clearForFlash(ERROR_MESSAGE_KEY_TO_FLASH, null, type); clearForSession(ERROR_MESSAGE_KEY_TO_SESSION, null, type); } /** * ストアされているエラー・メッセージをクリアします。 * このメソッドは指定されたキーが格納されているスコープは関係なく、削除します。 * @param code メッセージを指定するキー */ public void clearErrorMessage(String code) { MessageType type = MessageType.ERROR; clearForRequest(ERROR_MESSAGE_KEY_TO_REQUEST, code, type); clearForFlash(ERROR_MESSAGE_KEY_TO_FLASH, code, type); clearForSession(ERROR_MESSAGE_KEY_TO_SESSION, code, type); } /** * 指定されたスコープにストアされているインフォメーション・・メッセージをクリアします。 * @param scope スコープ */ public void clearInformationMessage(Scope scope) { Args.checkNotNull(scope); MessageType type = MessageType.INFORMATION; switch (scope) { case FLASH: clearForFlash(INFORMATION_MESSAGE_KEY_TO_FLASH, null, type); break; case SESSION: clearForSession(INFORMATION_MESSAGE_KEY_TO_SESSION, null, type); break; case REQUEST: default: clearForRequest(INFORMATION_MESSAGE_KEY_TO_REQUEST, null, type); break; } } /** * 指定されたスコープにストアされているエラー・メッセージをクリアします。 * @param scope スコープ */ public void clearErrorMessage(Scope scope) { Args.checkNotNull(scope); MessageType type = MessageType.ERROR; switch (scope) { case FLASH: clearForFlash(ERROR_MESSAGE_KEY_TO_FLASH, null, type); break; case SESSION: clearForSession(ERROR_MESSAGE_KEY_TO_SESSION, null, type); break; case REQUEST: default: clearForRequest(ERROR_MESSAGE_KEY_TO_REQUEST, null, type); break; } } private void clearForRequest(String key, String code, MessageType type) { Messages messages = (Messages) request.getAttribute(key); if (messages == null) return; if (Strings.isEmpty(code)) { request.removeAttribute(key); } else { messages.remove(code); request.setAttribute(key, messages); } } private void clearForFlash(String key, String code, MessageType type) { FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request); Messages messages = (Messages) flashMap.get(key); if (messages == null) return; if (Strings.isEmpty(code)) { flashMap.remove(key); } else { messages.remove(code); flashMap.put(key, messages); } } private void clearForSession(String key, String code, MessageType type) { HttpSession session = request.getSession(false); if (session == null) return; Messages messages = (Messages) session.getAttribute(key); if (messages == null) return; if (Strings.isEmpty(code)) { session.removeAttribute(key); } else { messages.remove(code); session.setAttribute(key, messages); } } /** * 現在のリクエストで有効な{@code MessageContext} インスタンスを返却します。 * @param request {@link HttpServletRequest} インスタンス * @return 現在のリクエストで有効な{@code MessageContext} インスタンス */ public static MessageContext getCurrentMessageContext(HttpServletRequest request) { MessageContext context = (MessageContext)request.getAttribute(MessageContext.MESSAGE_CONTEXT_ATTRIBUTE_KEY); if (context == null) context = new MessageContext(request); return context; } /** * MessageContextに設定されたリクエストを返します。 * @return リクエスト */ public HttpServletRequest getRequest() { return request; } }