/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKUBatStringUtil
*	ソースファイル名：JKUBatStringUtil.java
*	作成者			：富士通
*	日付			：2011年07月13日
*＜機能概要＞
*	文字列編集を行う共通機能を提供する。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/07/13	富士通		新規作成
*
**********************************************************************/
package eo.business.common;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;

import eo.business.util.table.JBSbatZM_M_KYOKU_NO;
import eo.common.constant.JKUStrConst;
import eo.common.constant.JPCBatchMessageConstant;
import eo.framework.application.JBSbatBusinessError;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatServiceInterfaceMap;

/**
 * 文字列編集を行う共通処理を行うクラスです。<p>
 * <br>
 * @author 富士通
 */
public class JKUBatStringUtil extends JCCBatCommon
{
	
	/** SQL定義キー(KU_SELECT_001)*/
	private static final String KYOKU_NO_SELECT_001 = "KU_SELECT_001";

	/**  全角アスタリスク */
	private static final String ZEN_ASTERISK = "＊";

	/** 東日本エリア */
	private static final String AREA_EAST = "03";

	/** 西日本エリア */
	private static final String AREA_WEST = "06";
	
	/** デフォルトキャラセット*/
	private static final String DEFAULT_CHARSET = "MS932";
	
	/** 基本お客様名分割文字数:15 */
	private static final int DEFAULT_END_STR_CNT = 15;
	
	/** 
	 * 01区と05区の全角カナ用の文字列対応表 
	 */
	private static final String[] ZENKAKU_0105 = {
		"　", "、", "。", "．", "・", "：", "；", "？", "！", "゛", "゜", "｀", "＾",
		"＿", "ー", "―", "‐", "／", "＼", "〜", "｜", "‘", "’", "（", "）", "［",
		"］", "｛", "｝", "「", "」", "＋", "−", "＝", "＜", "＞", "￥", "＄", "％",
		"＃", "＆", "＊", "＠", "ヮ", "ヰ", "ヱ","ヵ","ヶ"
	};
	
	/** 
	 * 01区と05区の半角カタカナ用の文字列対応表 
	 */
	private static final String[] HANKAKU_0105 = {
		" ", "､", "｡", ".", "･", ":", ";", "?", "!", "ﾞ", "ﾟ", "`", "^",
		"_", "-", "-", "-", "/", "\\", "~", "|", "`", "'", "(", ")", "[",
		"]", "{", "}", "｢", "｣", "+", "-", "=", "<", ">", "\\", "$", "%",
		"#", "&", "*", "@", "ﾜ", "ｲ", "ｴ","ｶ","ｹ"
	};
	
	/** 半角変換できない文字 */
	private static final String FALSE_CONVERT = " ";
	
	/** 半角文字サイズ */
	private static final int HALF_SIZE = 1;
	
	/**
	 * お客様名１を取得します。
	 * @param arg0 お客様名
	 * @param isMask true:２〜１５文字までの有効文字を「＊」に変換する。false:変換しない。
	 * @return  引数のお客様名の１文字目はそのまま、２〜１５文字までの有効文字は引数で変換制御した文字列
	 */
	public static String getCustName1(String arg0, boolean isMask)
	{
		return getCustName1(arg0, isMask, DEFAULT_END_STR_CNT);
	}
	
	/**
	 * お客様名２を取得します。
	 * @param arg0 お客様名
	 * @param isMask true:１６文字以降の有効文字を「＊」に変換する。false:変換しない。
	 * @return  引数のお客様名の１６文字以降の有効文字を引数で変換制御した文字列
	 */
	public static String getCustName2(String arg0, boolean isMask)
	{
		return getCustName2(arg0, isMask, DEFAULT_END_STR_CNT);
	}
	
	/**
	 * お客様名１を取得します。
	 * @param arg0 お客様名
	 * @param isMask true:２〜endStrCnt文字までの有効文字を「＊」に変換する。false:変換しない。
	 * @param endStrCnt 終了文字数 1文字目からここで指定された終了文字数までをお客様名１として処理を行う
	 * @return  引数のお客様名の１文字目はそのまま、２〜endStrCnt文字までの有効文字は引数で変換制御した文字列
	 */
	public static String getCustName1(String arg0, boolean isMask, int endStrCnt)
	{
		StringBuffer custName1 = new StringBuffer();
		
		if(null == arg0)
		{
			return "";
		}
		if (0 == endStrCnt)
		{
			return "";
		}
		
		//１文字目はそのまま、２文字目〜１５文字を＊に変換する
		for(int i = 0; i < arg0.length(); i++)
		{
			if(i == endStrCnt)
			{
				break;
			}
			
			if(isMask)
			{
				if(i == 0)
				{
					custName1.append(arg0.substring(0, 1));
				}
				else
				{
					custName1.append(ZEN_ASTERISK);
				}
			}
			else
			{
				custName1.append(arg0.substring(i, i + 1));
			}
		}
		
		return custName1.toString();
	}
	
	/**
	 * お客様名２を取得します。
	 * @param arg0 お客様名
	 * @param isMask true:(nm1EndStrCnt + 1)文字以降の有効文字を「＊」に変換する。false:変換しない。
	 * @param nm1EndStrCnt 除外文字数 1文字目からここで指定された除外文字数までをお客様名１として処理から除外し、以降の文字をお客様名２として処理を行う
	 * @return  引数のお客様名の(nm1EndStrCnt + 1)文字以降の有効文字を引数で変換制御した文字列
	 */
	public static String getCustName2(String arg0, boolean isMask, int nm1EndStrCnt)
	{
		StringBuffer custName2 = new StringBuffer();
		
		if(null == arg0)
		{
			return "";
		}
		
		//１６文字目以降を＊に変換する
		for(int i = nm1EndStrCnt; i < arg0.length(); i++)
		{
			if(isMask)
			{
				custName2.append(ZEN_ASTERISK);
			}
			else
			{
				custName2.append(arg0.substring(i, i + 1));
			}
		}
		
		return custName2.toString();
	}
	
	/**
	 * 住所コードの上５桁を取得します。
	 * @param arg0 住所コード
	 * @return 住所コードの上５桁、引数が５桁未満、またはnullの場合はそのままの値
	 */
	public static String getPlaceAdCd5keta(String arg0)
	{
		if(null == arg0)
		{
			return "";
		}
		else if(arg0.length() < 5)
		{
			return arg0;
		}
		else
		{
			return arg0.substring(0, 5);
		}
	}

	/**
	 * 電話番号を市外局番、市内局番、加入者番号に分割する。
	 * 
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @param tln 電話番号。数字だけで構成された9桁以上の文字列。
	 * @param db_ZM_M_KYOKU_NO	テーブルアクセスクラス(番ポ可能エリア対象局番)
	 * @return 分割した番号を格納した配列。引数の電話番号がnullの場合はnullを返す。
	 * @throws Exception      業務サービス内で発生した例外全般。
	 */
	public String[] splitTln(JBSbatCommonItem commonItem, String tln, JBSbatSQLAccess db_ZM_M_KYOKU_NO) throws Exception 
	{
		if (!isNotNull(tln)) 
		{
			return null;
		}
		if (!isTel2(tln)) 
		{
			// throw new Exception("正しい電話番号を設定してください。");
			// ログ出力し、次レコードへ
			commonItem.getLogPrint().printBusinessErrorLog(JPCBatchMessageConstant.EKUB0050TE, new String[]{
					"電話番号",
					tln});
			
			throw new JBSbatBusinessError();
		}
		
		if (tln.length() == 11) 
		{
			// 電話番号が11桁の場合
			// 999-9999-9999に編集する。
			return formatTelNoAdd2(tln).split("-");
		}
		else
		{
			// 上記以外の桁数の場合
			// 局番テーブルより市外局番取得
			
			// 条件を設定
			JBSbatCommonDBInterface whereMap = new JBSbatCommonDBInterface();
			// 局番設定
			String kyokuNo = tln.substring(0, 6);
			whereMap.setValue(kyokuNo); 							// 局番
			whereMap.setValue(commonItem.getOpeDate()); 			// 運用日
			
			db_ZM_M_KYOKU_NO.selectBySqlDefine(whereMap, KYOKU_NO_SELECT_001);
			
			JBSbatCommonDBInterface mapKyokuNo = db_ZM_M_KYOKU_NO.selectNext();
			
			String[] splitedTln = new String[3];
				
			if(mapKyokuNo == null)
			{
				
				String areaCd = tln.substring(0, 2);
				
				// 市外局番が関西圏内で無く、かつ関東の市外局番2桁で無い場合
				if (false == AREA_WEST.equals(areaCd) && false == AREA_EAST.equals(areaCd))
				{
					// 市外局番を3桁で取り直す
					areaCd = tln.substring(0, 3);
				}
				
				splitedTln[0] = areaCd; 																		// 市外局番
				splitedTln[1] = kyokuNo.substring(areaCd.length()); 											// 市内局番
				splitedTln[2] = tln.substring(kyokuNo.length()); 												// 加入者番号
			}
			else
			{
				splitedTln[0] = mapKyokuNo.getString(JBSbatZM_M_KYOKU_NO.AREACD); 								// 市外局番
				splitedTln[1] = kyokuNo.substring(mapKyokuNo.getString(JBSbatZM_M_KYOKU_NO.AREACD).length()); 	// 市内局番
				splitedTln[2] = tln.substring(kyokuNo.length()); 												// 加入者番号
			}
			
			return splitedTln;
		}
	}
	
	/**
	 * 値がNullの場合、指定した値を設定する。
	 * <br>
	 * @param checkValue 調整する文字列
	 * @param setValue 設定する値
	 * @return String 変換結果文字列
	 */
	public static String changeNullValue(Object checkValue, String setValue) 
	{
		if (!isNotNull(checkValue)) 
		{
			return setValue;
		}
		return checkValue.toString();
	}
	
	/**
	 * 郵便番号をハイフン編集する。
	 * 
	 * @param arg0 郵便番号
	 * @return 郵便番号を編集した値。
	 */
	public String editPcd(String arg0)
	{
		if(null == arg0)
		{
			return "";
		}
		else if(arg0.length() < 7)
		{
			return arg0;
		}
		
		String pcd = arg0.substring(0, 3) + "-" + arg0.substring(3, 7);

		return pcd;
	}

	/**
	 * カンマ編集を行います。
	 * @param infoMap　入力電文
	 * @param indexMap　項目名Map
	 * @return resultString　出力文字列
	 * @throws Exception 
	 */	
	public static StringBuilder editComma(JBSbatServiceInterfaceMap infoMap, HashMap<Object, String> indexMap) throws Exception
	{
		// Count変数
		int cnt = 0;
		
		// カンマ編集された文字列を格納する変数
		StringBuilder resultString = new StringBuilder();
		
		while (indexMap.get(cnt) != null)
		{
			if (infoMap.getString(indexMap.get(cnt)) != null)
			{
				// indexMapを基にカンマ編集,囲み編集を行う。
				resultString.append(infoMap.getString(indexMap.get(cnt)) + JKUStrConst.CSV);
			}	
			
			cnt++;
		}
		
		return resultString.delete(resultString.length() - 1, resultString.length());
	}
	
	/**
	 * 文字列の分割を行う。
	 * @param inString　入力文字列
	 * @param splitLen　入力分割文字数(入力分割バイト数)
	 * @param isByteSplit　バイト分割フラグ
	 * @return resultString　出力文字列
	 * @throws UnsupportedEncodingException 
	 */
	public static String[] splitString(String inString, int splitLen, boolean isByteSplit) throws UnsupportedEncodingException
	{
		// 返却する文字列を格納する配列
		String[] resultString = new String[2];
		resultString[0] = null;
		resultString[1] = null;
		
		// 入力文字列がnullの場合は、空文字の配列を返却する
		if (inString == null)
		{
			return resultString;
		}

		// バイト分割フラグに応じて処理を行う(true:バイト数分割、false:文字数分割)
		if (isByteSplit)
		{
			// バイト数による分割を行う
			if (inString.getBytes(DEFAULT_CHARSET).length <= splitLen)
			{
				// 入力文字列が分割バイト数以下の場合は分割しない
				resultString[0] = inString;
			}
			else
			{
				// 入力文字列を分割バイト数で分割する
				int count = 0;
				int i = 0;
				StringBuffer sbfString = new StringBuffer();
				while (count < splitLen)
				{
					String sbstrChar = inString.substring(i, i + 1);
					byte[] byteChar = sbstrChar.getBytes(DEFAULT_CHARSET);
					// 分割バイト数を超える場合はループを抜ける
					if (count + byteChar.length > splitLen) 
					{
						break;
					}
					else
					{
						count = count + byteChar.length;
						sbfString.append(sbstrChar);
					}
					i++;
				}
				resultString[0] = sbfString.toString();
				resultString[1] = inString.substring(i);
			}
		}
		else
		{
			// 文字数による分割を行う
			if (inString.length() <= splitLen)
			{
				// 入力文字列が分割文字数以下の場合は分割しない
				resultString[0] = inString;
			}
			else
			{
				// 入力文字列を分割文字数で分割する
				resultString[0] = inString.substring(0, splitLen);
				resultString[1] = inString.substring(splitLen);
			}
		}
		return resultString;
	}
	
	/**
	 * 全角記号と全角特殊文字を半角に変換した結果を
	 * 「変換された文字列」として、返却します。
	 * <br>
	 * @param convStr 変換する文字列
	 * @return String 変換された文字列
	 * @throws UnsupportedEncodingException 
	 */
	public static String convertHalfSign(String convStr) throws Exception
	{
		
		if(null == convStr || true == "".equals(convStr))
		{
			return convStr;
		}
		
		StringBuffer strBuf = new StringBuffer();

		// 文字列のサイズ分繰り返す
		for(int i = 0; i < convStr.length(); i++) 
		{
			// 一文字取り出す
			String code = convStr.substring(i, i + 1);

			// 取り出した対象文字のサイズが半角サイズより大きい場合、変換処理対象となる
			if(code.getBytes(DEFAULT_CHARSET).length > HALF_SIZE) 
			{

				for(int j = 0; j < ZENKAKU_0105.length; j++) 
				{
					if(code.equals(ZENKAKU_0105[j])) 
					{
						
						code = HANKAKU_0105[j];
						
						break;
						
					}
				}

				// 対象文字のサイズが半角サイズより大きい場合、半角空白を設定する
				if(code.getBytes(DEFAULT_CHARSET).length > HALF_SIZE) 
				{
					code = FALSE_CONVERT;
				}

			}

			// 文字をつなげる
			strBuf.append(code);
			
		}

		return strBuf.toString();
	}
	
}
