/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JCCMessageCache
*   ソースファイル名：JCCMessageCache.java
*   作成者          ：富士通
*   日付            ：2011年04月01日
*＜機能概要＞
*  最新のメッセージ定義ファイルの情報をHashMapに保持します。
*  メッセージIDと置換文字よりメッセージを設定し返却します。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*
**********************************************************************/

package eo.web.webview.common;

import java.util.HashMap;
import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;

import com.fujitsu.futurity.model.common.JCMAPLConstMgr;
import eo.common.util.JCCFrameworkException;

public class JCCMessageCache extends DefaultHandler
{
	/**　　メッセージ定義ファイル情報　*/
    private static HashMap<String, String> mapMsg = null;
    
	/**　　メッセージ定義ファイル情報取得用　*/
    private static HashMap<String, String> tempMapMsg = null;
    
	/**　　メッセージID　*/
    private static String messageID = null;
    
	/**　　メッセージ内容　*/
    private static String messageValue = null;
    
	/**　　メッセージIDのアトリビュート　*/
    private static final String ATT_ID = "id";
    
	/**　　メッセージ内容　*/
    private static final String ATT_VALUE = "value";
    
	/**　　前回ファイル更新日時　*/
    private static long curTimestamp = 0;
    
	/**　　前回ファイルサイズ　*/
    private static long curFileSize = 0;
	
	/**　　メッセージID無しエラー　*/
	private static final String ERR_MES_NO_ID = "メッセージIDが設定されていません。";

	/**　　置換文字無しエラー　*/
	private static final String ERR_MES_NO_REP = "置換文字が設定されていません。";
	
	/** JS格納先のパス */
	private static String jsPath = "";

    /**
     * メッセージ定義ファイルを読み込みHashMapに設定します。
     * <br>
     * @param context ディスパッチコンテキスト
	 * @exception 	JCCFrameworkExceptionがスローされます。
	 * @exception 	Exceptionがスローされます。
     */
    public synchronized static void setMessageCache() throws JCCFrameworkException, Exception
    {
		// プロパティファイルからファイルパスを取得する。
		String MESSAGE_FILE_PATH = JCMAPLConstMgr.getString(JCMAPLConstMgr.MESSAGE_FILE_PATH);
	    File file = new File(MESSAGE_FILE_PATH);
	    if(!file.exists() || !file.isFile() || !file.canRead())
	    {
	    	throw new JCCFrameworkException("メッセージ定義ファイルが設定されていません。");
	    }
	    long size = file.length();
	    // 初回および更新時のみファイル読み込みを行う。
	    if (mapMsg == null || curTimestamp != file.lastModified() || curFileSize != size)
	    {
	    	mapMsg = new HashMap<String, String>();
	        
	    	// サイズが前の状態と違っていたら、同じになるまで読み込み処理をはじめない。
	    	while(curFileSize != size)
	    	{
	    		// 現在の状態をクラス変数に退避する。
	    		curFileSize =  size;
	    		// 5ms後に再度ファイルサイズを確認する。
	    		Thread.sleep(5);
	    		file = new File(MESSAGE_FILE_PATH);
	    		size =  file.length();
	    	}
	    	JCCMessageCache handler = new JCCMessageCache();
			// パーサを作成する。
			SAXParserFactory spf = SAXParserFactory.newInstance();
			spf.setNamespaceAware(false);
			spf.setValidating(false);
			spf.setXIncludeAware(false);
			// 定義ファイルを解析し、メッセージ情報をHashMapに設定する。
			SAXParser sp = spf.newSAXParser();
			tempMapMsg = new HashMap<String, String>();
			sp.parse(file, handler);
			mapMsg = tempMapMsg;
			tempMapMsg = null;
	        curTimestamp = new File(MESSAGE_FILE_PATH).lastModified();
	    }
    }
    
    /**
     * XMLの開始要素をSAXPerserで解析します。
     * <br>
     */
	@Override
	public void startElement(String uri,String localName, String qName, Attributes attrs)
	{
		if(qName.equals("メッセージID"))
		{
			JCCMessageCache.messageID = attrs.getValue(JCCMessageCache.ATT_ID);
		}else if(qName.equals("メッセージ情報"))
		{
			JCCMessageCache.messageValue = attrs.getValue(JCCMessageCache.ATT_VALUE);
		}
	}
	
    /**
     * XMLの終了要素をSAXPerserで解析します。
     * <br>
     */
	@Override
	public void endElement(String uri, String localName, String qName)
	{
		if(qName.equals("メッセージID"))
		{
			// メッセージIDかメッセージがなければ設定しない。
			if(messageID != null && messageValue != null)
			{
				tempMapMsg.put(messageID, messageValue);
			}
		}
	}
	
	/**
	 * Documentの解析終了で処理を行います。
	 * 
	 */
	public void endDocument()
	{
		String targetSystem = JCCWebCommon.getApplicationConst("TARGET_SYSTEM");
		// 2012/02/15 FST)arata 量販タイプを追加 start
		if ("FRONT".equals(targetSystem) || "RYOHAN".equals(targetSystem))
		// 2012/02/15 FST)arata 量販タイプを追加 end
		{
			JCCCreateMsgJS.createFile(tempMapMsg, jsPath);
		}
	}
    
    /**
     * クライアント用のメッセージを返却します。
     * @return HashMap
     */
    public static HashMap<String, String> getMessageMap()
    {
    	return mapMsg;
    }

    /**
     * メッセージIDと置換文字を基にメッセージを設定し返却します。
     * <br>
	 * @param msgId			メッセージID
	 * @param rep			置換文字
     * @return String		置換メッセージ
     */
	public static String getMessage(String msgId, String[] rep) throws JCCFrameworkException
	{
		// メッセージIDの入力チェックを行う。
		if(msgId == null || "".equals(msgId))
		{
			throw new JCCFrameworkException(JCCMessageCache.ERR_MES_NO_ID);
		}
		// 置換文字の入力チェックを行う。
		if(rep == null || rep.length == 0)
		{
			throw new JCCFrameworkException(JCCMessageCache.ERR_MES_NO_REP);
		}
        // 置換文字の文字列置換
        return replaceCharacter(getBaseMessage(msgId),rep);
	}


    /**
     * メッセージIDを基にメッセージを設定し返却します。
     * <br>
	 * @param msgId		メッセージID
     * @return String	メッセージ
     */
	public static String getMessage(String msgId) throws JCCFrameworkException
	{
		// メッセージIDの入力チェックを行う。
		if(msgId == null || "".equals(msgId))
		{
			throw new JCCFrameworkException(JCCMessageCache.ERR_MES_NO_ID);
		}
        return getBaseMessage(msgId);
	}
	
	private static String getBaseMessage(String msgId) {
		// メッセージを取得する。
        String message = (String)mapMsg.get(msgId);
        // バックヤード／フロントの判定用文字列を取得
        String targetSystem = JCCWebCommon.getApplicationConst("TARGET_SYSTEM");
        // メッセージが設定されていない場合
        if(message == null)
        {
        	if ("BACKYARD".equals(targetSystem))
        	{
        		return "[" + msgId + "]";
        	}
        	
        	return "";
        }
        
        if ("BACKYARD".equals(targetSystem))
    	{
        	message += "[" + msgId + "]";
    	}
        
		return message;
	}
	
	
	/**
	 * メッセージに置換文字の設定を行う。
	 * <br>
	 * @param msg		メッセージ
	 * @param rep		置換文字配列
	 * @return			置換後メッセージ
	 */
	private static String replaceCharacter(String msg,String[] rep)
	{
		for(int i=0;i<rep.length;i++)
		{
			msg = msg.replace("%"+(i+1)+"%", rep[i]);
		}
		return msg;
	}

	/**
	 * JS格納先のパスを設定する。
	 * <br>
	 * @param path JS格納先のパス
	 */
	public static void setJsPath(String path) {
		jsPath = path;
	}

}
