/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom  					 *
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatRknBusinessUtil
*	ソースファイル名	：JBSbatRknBusinessUtil.java
*	作成者				：富士通　
*	作成日				：2011年07月04日
*＜機能概要＞
*　料金業務共通クラスです。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/07/04   富士通		新規作成
*	v3.00		2012/08/06   FJ）冨井	【TAI-2012-0000094】コンストラクタ、税額計算部品修正
*	v3.01		2012/08/31   FJ）冨井	【ST2-2012-0001602】埋め込み文字置換汎用処理追加
*	v4.00		2013/01/25   FJ) 小柴	【内部管理番号-0000702】値の範囲チェック用処理追加
*	v4.01		2013/06/08   FJ) 狭間	【TG1-2013-0000550】税額計算処理の小数点以下有版を追加
*	v5.00		2013/09/10   FJ) 小柴	【OM-2013-0001631】サービスインターフェイスエラー時の処理を異常終了から警告終了に変更
*	v8.00		2014/05/27   FJ) 小掠	【OM-2014-0001682】0/0.0のときパラメータを返していたのを返さないように変更
*	v55.00.00	2021/10/01   FJ)森脇	【ANK-4121-00-00】貸倒対象者一覧のマイナス金額出力対応
*********************************************************************/
package eo.business.common;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import eo.business.util.table.JBSbatAC_M_FILE_GENE_CTRL;
import eo.business.util.table.JBSbatAC_M_TAX_RT;
import eo.common.constant.JACStrConst;
import eo.common.constant.JPCBatchMessageConstant;
import eo.common.util.JPCEditString;
import eo.common.util.JPCUtilCommon;
import eo.framework.application.JBSbatBusinessException;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.log.JBSbatLogPrintControl;
import eo.framework.util.JBSbatBusinessFileUtil;
import eo.framework.util.JCCBatchEsbInterface;

/**
 * 料金業務共通クラスです。<p>
 * <BR>
 * @author 富士通
 */
public class JACbatRknBusinessUtil
{
	
	/** ＳＱＬ定義キー：税率マスタ*/
	private static final String SQLDEFKEY_ZERITU = "AC_SELECT_001";

	/** ＳＱＬ定義キー：ファイル生成制御マスタ*/
	private static final String SQLDEFKEY_GENE_FILE = "AC_SELECT_002";

	/** 丸め方法：四捨五入 */
	private static final String ROUND_OFF 		= "1";

	/** 丸め方法：切上げ */
	private static final String ROUND_UP 			= "2";

	/** 丸め方法：切捨て */
	private static final String ROUND_DOWN 		= "3";

	/** 内税外税区分：内税 */
	private static final String UCHI_SOTO_KBN1 	= "1";

	/** 内税外税区分：外税 */
	private static final String UCHI_SOTO_KBN2 	= "2";

	/** 税区分：外税 */
	private static final String TAX_KBN1 	= "1";

	/** 税区分：内税 */
	private static final String TAX_KBN2 	= "2";

	/** 税区分：非課税 */
	private static final String TAX_KBN3 	= "3";

	/** 税区分：対象外 */
	private static final String TAX_KBN4 	= "4";
	
	private static final BigDecimal HUNDRED = new BigDecimal("100");

	/** 税率マスタ 検索結果 */
	private HashMap<String, ArrayList<JBSbatCommonDBInterface>> zerituMap = new HashMap<String, ArrayList<JBSbatCommonDBInterface>>();
	
	/** 退避．KEY（税計算区分＋基準日） */
	private String tmpKey = JACStrConst.KARA_MOJI;
	
	/** 退避．税率マスタ */
	private JBSbatCommonDBInterface tmpZerituInfo = null;
	
	/** 年月日書式(yyyyMMdd)の桁数 */
	private static final int YMD = 8;
	
	/** 年 */
	private static final String STR_YEAR = "年";
	
	/** 月 */
	private static final String STR_MONTH = "月";
	
	/** 日 */
	private static final String STR_DAY = "日";
	
	/** 改行CR */
	private static final String KAIGYO_CR = "KAIGYO_CR";
	
	/** 改行LF */
	private static final String KAIGYO_LF = "KAIGYO_LF";
	
	/** 改行CRLF */
	private static final String KAIGYO_CRLF = "KAIGYO_CRLF";
	
	/** 改行CR */
	private static final String CR = "CR";
	
	/** 改行LF */
	private static final String LF = "LF";
	
	/** 改行CRLF */
	private static final String CRLF = "CR+LF";

	/**
     * コンストラクタ（デフォルト）
     * 
     */
	public JACbatRknBusinessUtil()
	{

	}

	/**
     * コンストラクタです。（税率マスタ参照時）<BR>
     * 税率マスタを検索し、検索結果をthis.zerituMapに格納します。
     * ※初期処理にて呼び出して下さい。<BR>
     * 
     * @param commonItem バッチ共通電文
     * @throws Exception
     */
	public JACbatRknBusinessUtil(JBSbatCommonItem commonItem) throws Exception
	{
		// テーブルアクセスクラス生成
		JBSbatSQLAccess dbAccess = new JBSbatSQLAccess(commonItem, JBSbatAC_M_TAX_RT.TABLE_NAME); // 税率マスタ

		// 検索結果をHashMapに設定
		this.zerituMap = new HashMap<String, ArrayList<JBSbatCommonDBInterface>>();
		// 前回KEY、退避税率マスタに初期値設定
		this.tmpKey 		= JACStrConst.KARA_MOJI;
		this.tmpZerituInfo 	= null;
		
		ArrayList<JBSbatCommonDBInterface> dbInfoList = new ArrayList<JBSbatCommonDBInterface>();
		
		// 対象キーの設定
		JBSbatCommonDBInterface dbSelectList = new JBSbatCommonDBInterface();

		// SELECT文発行
		dbAccess.selectBySqlDefine(dbSelectList, SQLDEFKEY_ZERITU);
		
		// 結果を取得
		JBSbatCommonDBInterface dbMap = dbAccess.selectNext();
		
		// 取得出来た場合
		if(dbMap != null)
		{	
			String tihKey 	= dbMap.getString(JBSbatAC_M_TAX_RT.TAX_CALC_SKBT_CD);	// 税計算区分
			// 検索結果がなくなるまで繰り返す
			while(dbMap != null)
			{
				String key = dbMap.getString(JBSbatAC_M_TAX_RT.TAX_CALC_SKBT_CD);	// 税計算区分
				// キーが同じ場合、リストに追加
				if(key.equals(tihKey))
				{
					dbInfoList.add(dbMap);
				}
				// キーブレイクの場合
				else
				{
					this.zerituMap.put(tihKey, dbInfoList);					// HashMapへ設定
					tihKey = key;											// 退避キーの置き換え
					dbInfoList = new ArrayList<JBSbatCommonDBInterface>();	// 初期化
					dbInfoList.add(dbMap);
				}
				// 次レコード取得
				dbMap = dbAccess.selectNext(); 
			}
			this.zerituMap.put(tihKey, dbInfoList);		// HashMapへ設定
		}
		// テーブルアクセスクラス クローズ
		dbAccess.close();
	}

	/**
	 * 税額計算処理を行います。<BR>
	 * ※コンストラクタJBSbatRknBusinessUtil(commonItem)を呼び出してから実行しないと、税率マスタの内容を使用出来ません。<BR>
	 * ※前回の呼出情報（税計算区分＋基準日）が同じ場合は、前回検索結果の税率マスタを使用します。<BR>
	 * @param tax_kbn 税計算区分
	 * @param ryokin 料金
	 * @param stdardYmd 基準日
	 * @return BigDecimal[] 0:税額、1:税率
	 * @throws Exception
	 */
	public BigDecimal[] calcTaxCharge(String tax_kbn, BigDecimal ryokin, String stdardYmd)
			throws Exception
	{
// ANK-4121-00-00 ADD START
		return calcTaxCharge( tax_kbn,  ryokin,  stdardYmd,  true);
	}
	/**
	 * 税額計算処理を行います。<BR>
	 * ※コンストラクタJBSbatRknBusinessUtil(commonItem)を呼び出してから実行しないと、税率マスタの内容を使用出来ません。<BR>
	 * ※前回の呼出情報（税計算区分＋基準日）が同じ場合は、前回検索結果の税率マスタを使用します。<BR>
	 * @param tax_kbn 税計算区分
	 * @param ryokin 料金
	 * @param stdardYmd 基準日
	 * @param isTaxRtT 税率適用日の判定（true:判定する false:判定しない）
	 * @return BigDecimal[] 0:税額、1:税率
	 * @throws Exception
	 */
	public BigDecimal[] calcTaxCharge(String tax_kbn, BigDecimal ryokin, String stdardYmd, boolean isTaxRtT)
			throws Exception
	{
// ANK-4121-00-00 ADD END
		// 返却情報を生成する
		BigDecimal[] returnValue = new BigDecimal[2];
		BigDecimal   taxCharge   = BigDecimal.ZERO; // 税額（出力）
		BigDecimal   taxRate     = BigDecimal.ZERO; // 税率（出力）
		
		// 判定値取得
		StringBuffer strBuf 		= new StringBuffer();
		strBuf.append(tax_kbn);
		strBuf.append(stdardYmd);
		String key = strBuf.toString();

		// 退避．KEY（税計算区分＋基準日） ≠ 入力．KEY（税計算区分＋基準日）の場合
		if(!key.equals(this.tmpKey))
		{
			ArrayList<JBSbatCommonDBInterface> dbInfoList = this.zerituMap.get(tax_kbn);
			this.tmpZerituInfo = null;
			if(dbInfoList != null)
			{
				for(JBSbatCommonDBInterface dbMap : dbInfoList)
				{
					// 判定値取得
					String staYmd = dbMap.getString(JBSbatAC_M_TAX_RT.TAX_RT_TSTAYMD);
					String endYmd = dbMap.getString(JBSbatAC_M_TAX_RT.TAX_RT_TENDYMD);
					// 税率適用開始年月日 ≦ 基準日 かつ 基準日 ≦ 税率適用終了年月日の場合
					if(staYmd.compareTo(stdardYmd) <= 0
							&& stdardYmd.compareTo(endYmd) <= 0)
					{
						this.tmpZerituInfo = dbMap;
						break;
					}
// ANK-4121-00-00 ADD START
					if(!isTaxRtT)
					{
						this.tmpZerituInfo = dbMap;
						break;
					}
// ANK-4121-00-00 ADD END
				}
			}
			this.tmpKey = key;
		}

		// 税率マスタが存在する場合
		if (this.tmpZerituInfo != null)
		{
			// 税率（マスタ）を取得する
			BigDecimal mstTaxRate = this.tmpZerituInfo.getBigDecimal(JBSbatAC_M_TAX_RT.TAX_RT);

			// 税率（出力）を設定する
			taxRate = mstTaxRate;

			// 内税外税区分の取得
			String uchiSotoKbn = this.tmpZerituInfo.getString(JBSbatAC_M_TAX_RT.UZEI_SZEI_SKBT_CD);

			// 外税の場合
			if (uchiSotoKbn.equals(UCHI_SOTO_KBN2))
			{
				// 税額（出力）の計算を行う(税額＝料金×税率÷100)
				taxCharge = ryokin.multiply(mstTaxRate).divide(HUNDRED);
			}
			// 内税の場合
			else if (uchiSotoKbn.equals(UCHI_SOTO_KBN1))
			{
				// 税額（出力）の計算を行う(税額＝料金×税率÷(100+税率))
				taxCharge = ryokin.multiply(mstTaxRate).divide(HUNDRED.add(mstTaxRate), 4, BigDecimal.ROUND_HALF_EVEN);
			}

			// 丸め方法に従い、丸め処理を行う
			taxCharge = round(this.tmpZerituInfo.getString(JBSbatAC_M_TAX_RT.ROUND_WAY_CD), taxCharge, 0);
		} 
		// 税率マスタが存在しない場合
		else
		{ 
			// 税額、税率ともに初期値(0)のまま
		}

		// 返却情報を設定する
		returnValue[0] = taxCharge;
		returnValue[1] = taxRate;

		return returnValue;
	}

	/**
	 * 税額計算処理を行います。<BR>
	 * ※コンストラクタJBSbatRknBusinessUtil(commonItem)を呼び出してから実行しないと、税率マスタの内容を使用出来ません。<BR>
	 * ※前回の呼出情報（税計算区分＋基準日）が同じ場合は、前回検索結果の税率マスタを使用します。<BR>
	 * @param tax_kbn 税計算区分
	 * @param ryokin 料金
	 * @param stdardYmd 基準日
     * @param keta 小数点以下の桁数
	 * @return BigDecimal[] 0:税額、1:税率
	 * @throws Exception
	 */
	public BigDecimal[] calcTaxChargeEx(String tax_kbn, BigDecimal ryokin, String stdardYmd, int keta)
			throws Exception
	{
		// 返却情報を生成する
		BigDecimal[] returnValue = new BigDecimal[2];
		BigDecimal   taxCharge   = BigDecimal.ZERO; // 税額（出力）
		BigDecimal   taxRate     = BigDecimal.ZERO; // 税率（出力）
		returnValue[0] = taxCharge;
		returnValue[1] = taxRate;
		
		// パラメータチェック
		if(keta < 0 || keta > 100000000)
		{
			return returnValue;
		}

		// 判定値取得
		StringBuffer strBuf = new StringBuffer();
		strBuf.append(tax_kbn);
		strBuf.append(stdardYmd);
		String key = strBuf.toString();
		
		// 退避．KEY（税計算区分＋基準日） ≠ 入力．KEY（税計算区分＋基準日）の場合
		if(!key.equals(this.tmpKey))
		{
			ArrayList<JBSbatCommonDBInterface> dbInfoList = this.zerituMap.get(tax_kbn);
			this.tmpZerituInfo = null;
			if(dbInfoList != null)
			{
				for(JBSbatCommonDBInterface dbMap : dbInfoList)
				{
					// 判定値取得
					String staYmd = dbMap.getString(JBSbatAC_M_TAX_RT.TAX_RT_TSTAYMD);
					String endYmd = dbMap.getString(JBSbatAC_M_TAX_RT.TAX_RT_TENDYMD);
					// 税率適用開始年月日 ≦ 基準日 かつ 基準日 ≦ 税率適用終了年月日の場合
					if(staYmd.compareTo(stdardYmd) <= 0
							&& stdardYmd.compareTo(endYmd) <= 0)
					{
						this.tmpZerituInfo = dbMap;
						break;
					}
				}
			}
			this.tmpKey = key;
		}

		// 税率マスタが存在する場合
		if (this.tmpZerituInfo != null)
		{
			// 税率（マスタ）を取得する
			BigDecimal mstTaxRate = this.tmpZerituInfo.getBigDecimal(JBSbatAC_M_TAX_RT.TAX_RT);

			// 税率（出力）を設定する
			taxRate = mstTaxRate;

			// 内税外税区分の取得
			String uchiSotoKbn = this.tmpZerituInfo.getString(JBSbatAC_M_TAX_RT.UZEI_SZEI_SKBT_CD);

			// 外税の場合
			if (uchiSotoKbn.equals(UCHI_SOTO_KBN2))
			{
				// 税額（出力）の計算を行う(税額＝料金×税率÷100)
				taxCharge = ryokin.multiply(mstTaxRate).divide(HUNDRED);
			}
			// 内税の場合
			else if (uchiSotoKbn.equals(UCHI_SOTO_KBN1))
			{
				// 税額（出力）の計算を行う(税額＝料金×税率÷(100+税率))
				taxCharge = ryokin.multiply(mstTaxRate).divide(HUNDRED.add(mstTaxRate), 4, BigDecimal.ROUND_HALF_EVEN);
			}

			// 丸め方法に従い、丸め処理を行う
			taxCharge = round(this.tmpZerituInfo.getString(JBSbatAC_M_TAX_RT.ROUND_WAY_CD), taxCharge, keta);
		} 
		// 税率マスタが存在しない場合
		else
		{ 
			// 税額、税率ともに初期値(0)のまま
		}

		// 返却情報を設定する
		returnValue[0] = taxCharge;
		returnValue[1] = taxRate;

		return returnValue;
	}

	/**
     * 小数点第一位による丸め処理を行います。<BR>
     * 負の数の場合は絶対値を丸めた数に-1を乗算します。
     * <BR>
     * @param roundWay 丸め方法 1:四捨五入、2:切り上げ、3:切捨て、左記以外:丸めなし
     * @param num 丸め処理前の数値
     * @param keta 小数点以下の桁数
     * @return double 丸め処理後の数値
     */
	public static BigDecimal round(String roundWay, BigDecimal num, int keta)
	{
		BigDecimal retNum = null;

		// 符号を設定する
		 BigDecimal sign = new BigDecimal(num.signum());

		// 絶対値を取得する
		BigDecimal absNum = num.abs();

		// 丸め方法に従い、絶対値での丸め処理を行う
		// 四捨五入
		if (ROUND_OFF.equals(roundWay))
		{
			retNum = absNum.setScale(keta, RoundingMode.HALF_UP);
		}
		// 切上げ
		else if (ROUND_UP.equals(roundWay))
		{
			retNum = absNum.setScale(keta, RoundingMode.CEILING);
		}
		// 切捨て
		else if (ROUND_DOWN.equals(roundWay))
		{
			retNum = absNum.setScale(keta, RoundingMode.FLOOR);
		}
		// 丸めなし
		else
		{
			retNum = absNum;
		}

		// 符号を元に戻す
		retNum = retNum.multiply(sign);

		return retNum;
	}

	/**
	 * NULL判定を行います。
	 * <br>
	 * @param alg0 対象文字列
	 * @return true:NULL false:NULL以外
	 */
	public static boolean isNull(String alg0)
	{
		if(alg0 == null || alg0.length() == 0)
		{
			return true;
		}

		return false;
	}

	/**
	 * 料金サービスコードを0パディングでフル桁にします。
	 * 
	 * @param prcSvcCd 料金サービスコード
	 * @return 料金サービスコード（フル桁）
	 * @throws Exception 
	 */
	public static String fullPrcSvcCd(String prcSvcCd)throws Exception
	{              
		return JPCUtilCommon.fillHalfSpace(prcSvcCd, JACStrConst.PRC_SVC_CD_LENGTH, true);
	}
	
	/**
	 * ファイル名編集処理
	 * ファイル生成制御マスタより取得した値を基に動的にファイル名を編集する。
	 * @param fileNo		// ファイル連番
	 * @param dbMap			// ファイル生成制御マスタ情報
	 * @param fileKbnArray	// ファイル識別格納配列
	 * 							[0]：システムコード
	 * 							[1]：請求年月
	 * 							[2]：運用日
	 * 							[3]：システム日時
	 * 							[4]：（自由設定）
	 * 							[5]：多重番号
	 * @return	String[]	// ファイル名生成情報(20Byte右スペースパディング)
	 * 							[0]：ファイル識別１
	 * 							[1]：ファイル識別２
	 * 							[2]：ファイル識別３
	 * 							[3]：ファイル識別４
	 * 							[4]：ファイル識別５
	 * @throws Exception
	 */
	public static String[] editFileItemName(String fileNo, JBSbatCommonDBInterface dbMap, String[] fileKbnArray) throws Exception
	{
		String[] returnArray = new String[7]; 			// 返却用配列
		StringBuffer fileNameBuf = new StringBuffer(); 	// ファイル名バッファ
		String fileKbnName1 = "";
		String fileKbnName2 = "";
		String fileKbnName3 = "";
		String fileKbnName4 = "";
		String fileKbnName5 = "";

		// 出力ファイル名を設定する
		fileNameBuf.append(dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FOLDER_NM)); 	// フォルダ名（ファイル出力先）
		fileNameBuf.append(System.getProperty("file.separator")); 					// ファイル区切り文字
		fileNameBuf.append(dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FILE_NM)); 	// ファイル名
		// ファイル生成確定
		if ("000".equals(fileNo))
		{
			if (!" ".equals(dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_1)))
			{
				fileKbnName1 = fileKbnArray[dbMap.getBigDecimal(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_1).intValue() - 1]; // ファイル識別１
				fileNameBuf.append("_");
				fileNameBuf.append(fileKbnName1);
			}
			if (!" ".equals(dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_2)))
			{
				fileKbnName2 = fileKbnArray[dbMap.getBigDecimal(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_2).intValue() - 1]; // ファイル識別２
				fileNameBuf.append("_");
				fileNameBuf.append(fileKbnName2);
			}
			if (!" ".equals(dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_3)))
			{
				fileKbnName3 = fileKbnArray[dbMap.getBigDecimal(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_3).intValue() - 1]; // ファイル識別３
				fileNameBuf.append("_");
				fileNameBuf.append(fileKbnName3);
			}
			if (!" ".equals(dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_4)))
			{
				fileKbnName4 = fileKbnArray[dbMap.getBigDecimal(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_4).intValue() - 1]; // ファイル識別４
				fileNameBuf.append("_");
				fileNameBuf.append(fileKbnName4);
			}
			if (!" ".equals(dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_5)))
			{
				fileKbnName5 = fileKbnArray[dbMap.getBigDecimal(JBSbatAC_M_FILE_GENE_CTRL.FILE_SKBT_CD_5).intValue() - 1]; // ファイル識別５
				fileNameBuf.append("_");
				fileNameBuf.append(fileKbnName5);
			}
			fileNameBuf.append("."); // ドット
			String fileForm = dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FILE_FORM);
			fileNameBuf.append(fileForm); // ファイル形式

			// ファイル形式より区切り文字を編集する
			// csv(CSV)形式の場合
			if ("csv".equals(fileForm) || "CSV".equals(fileForm))
			{
				returnArray[1] = ","; // カンマ
			}
			// tsv(TSV)形式の場合
			else if ("tsv".equals(fileForm) || "TSV".equals(fileForm))
			{
				returnArray[1] = "\t"; // タブ
			}
			// 上記以外の場合
			else
			{
				returnArray[1] = ""; // 編集なし
			}
		}
		else
		{
			fileNameBuf.append("."); // ドット
			fileNameBuf.append(dbMap.getString(JBSbatAC_M_FILE_GENE_CTRL.FILE_FORM)); // ファイル形式
			fileNameBuf.append("."); // ドット
			fileNameBuf.append((JBSbatInterface.editFileNoFormat(Integer.parseInt(fileNo) - 1))); // ファイル連番
			// 区切り文字の設定
			returnArray[1] = ",";
		}

		returnArray[0] = fileNameBuf.toString(); // 出力ファイル名（フルパス）
		returnArray[2] = fileKbnName1;
		returnArray[3] = fileKbnName2;
		returnArray[4] = fileKbnName3;
		returnArray[5] = fileKbnName4;
		returnArray[6] = fileKbnName5;

		return returnArray;
	}
	
	/**
	 * ファイルに出力する情報を、項目ごとに指定された文字列で囲みます。
	 * 
	 * @param trgtMap 出力ファイル情報（編集前）
	 * @param leftChar 左囲み文字
	 * @param rightChar 右囲み文字
	 * @return 出力ファイル情報（編集後）
	 */
	@SuppressWarnings("unchecked")
	public static HashMap quote(Map trgtMap, String leftChar, String rightChar)
	{
		Set set = trgtMap.keySet();
		HashMap newMap = new HashMap();
		for (Iterator<String> i = set.iterator(); i.hasNext();)
		{
			String key = i.next();
			String value = (String) trgtMap.get(key);
			if (value == null)
			{
				value = JACStrConst.KARA_MOJI;
			}
			newMap.put(key, leftChar + value + rightChar);
		}
		
		return newMap;
	}
	
	/**
	 * 年月日書式(yyyy年MM月dd日)の編集を行います。
	 * <br>
	 * @param arg0 年月日書式に編集する文字列(yyyyMMdd)
	 * @return String 年月日書式に編集された文字列(yyyy年MM月dd日)
	 */
	public static String formatDate(String arg0) 
	{
		if(!isValidParameter(arg0, YMD)) 
		{
			return arg0;
		}
		
		StringBuffer buf = new StringBuffer();
		
		buf.append(JPCUtilCommon.toYearFromYmd(arg0));
		buf.append(STR_YEAR);
		buf.append(JPCUtilCommon.toMonthFromYmd(arg0));
		buf.append(STR_MONTH);
		buf.append(JPCUtilCommon.toDayFromYmd(arg0));
		buf.append(STR_DAY);

		return buf.toString();
	}
	
	/**
	 * 指定された文字列のバイト数を求めます。
	 * <br>
	 * @param str バイト数を求める文字列
	 * @param enc 文字列のエンコード
	 * @return int 求めたバイト数
	 */
	public static int getBytes(String str, String enc)  throws Exception
	{
		if(str == null || enc == null) 
		{
			return -1;
		}
		
		return str.getBytes(enc).length;
	}
	
	/**
	 * 改行コードを変換します。<br>
	 * 変換できない場合、空文字を返却する。
	 * <br>
	 * @param kaigyo 変換前改行コード
	 * @return 変換後改行コード
	 */
	public static String chgKaigyo(String kaigyo)
	{
		String result = "";
		if (CR.equals(kaigyo))
		{
			result = JCCBatCommon.getApplicationConst(KAIGYO_CR);
		}
		else if (LF.equals(kaigyo))
		{
			result = JCCBatCommon.getApplicationConst(KAIGYO_LF);
		}
		else if (CRLF.equals(kaigyo))
		{
			result = JCCBatCommon.getApplicationConst(KAIGYO_CRLF);
		}
		result = result.replaceAll("\\\\r", "\\\r");
		result = result.replaceAll("\\\\n", "\\\n");
		return result;
	}
	
	/**
	 * 有効なパラメータか判定します。
	 * 文字列に値が設定されていない場合、及び指定された桁数と
	 * 一致しない場合はエラーとします。
	 * <br>
	 * @param arg0 判定する文字列
	 * @param arg1 文字列として有効な桁数
	 * @return パラメータが不正な場合はfalse
	 */
	private static boolean isValidParameter(String arg0, int arg1) 
	{
		if (isNull(arg0)) 
		{
			return false;
		}

		return arg1 == arg0.length();
	}
	
	/**
	 * リストの要素をカンマ区切りの文字列に変換して返却します。
	 * <br>
	 * @param list 変換するリスト文字列
	 * @return String 変換された文字列
	 */
	public static String convListToString(ArrayList<String> list) 
	{
		StringBuffer buf = new StringBuffer();

		for (int i = 0; i < list.size(); i++) 
		{
			if (i > 0) 
			{
				buf.append(",");
			}

			if(list.get(i) == null) 
			{
				buf.append(JACStrConst.KARA_MOJI);
			}
			else
			{
				buf.append(list.get(i));
			}
		}
		return buf.toString();
	}
	
	/**
	 * 指定された桁数まで半角空白を充填します。
	 * <br>
	 * @param arg0 調整する文字列
	 * @param arg1 調整する長さ
	 * @param arg2 空白埋め左右判断フラグ（true：右埋め、false：左埋め）
	 * @return String 空白充填後の文字列
	 */
	public static String fillHalfSpace(String arg0, int arg1, boolean arg2) 
	{
		// 調整する文字列が空の場合、空白1桁に置き換えてfillHalfSpaceを呼び出す
		// ※空で呼び出した場合、パディングされないため
		if(JACStrConst.KARA_MOJI.equals(arg0))
		{
			return JPCEditString.fillHalfSpace(JACStrConst.SPACE_1, arg1, arg2);
		}
		else
		{
			return JPCEditString.fillHalfSpace(arg0, arg1, arg2);
		}
	}
	
	/**
	 * 指定されたファイルIDを基にファイル生成制御マスタを検索し、取得した値を基にファイル名を編集・ファイルオープンします。
	 * <br>
	 * @param commonItem バッチ共通パラメータ
	 * @param fileId ファイルID
	 * @param fileBnktUm ファイル分割有無
	 * @param fileNo ファイル連番
	 * @param seikyYm 請求年月
	 * @param freeSet 自由設定
	 * @param tajuNo 多重番号
	 * @param mojiCd 文字コード
	 * @param rowCd 変換前改行コード
	 * @return ArrayList<Object> ファイル生成情報配列（[0]:ファイル名（フルパス）、[1]:区切り文字、[2]:ファイルインスタンス）
	 */
	public static ArrayList<Object> geneFile(JBSbatCommonItem commonItem, String fileId, String fileBnktUm, String fileNo,
									String seikyYm, String freeSet, String tajuNo, String mojiCd, String rowCd) throws Exception
	{
		// DBアクセスクラス生成（ファイル生成制御）
		JBSbatSQLAccess dbAccess = new JBSbatSQLAccess(commonItem, JBSbatAC_M_FILE_GENE_CTRL.TABLE_NAME); // ファイル生成制御マスタ
		
		// 対象キーの設定
		JBSbatCommonDBInterface dbSelectList = new JBSbatCommonDBInterface();
		
		// パラメタ設定
		dbSelectList.setValue(commonItem.getSystemCode());	// システムコード
		dbSelectList.setValue(fileId);						// ファイルID
		dbSelectList.setValue(fileBnktUm);					// ファイル分割有無
		dbSelectList.setValue(fileNo);						// ファイル連番
		dbSelectList.setValue(commonItem.getOpeDate());		// 運用日
		dbSelectList.setValue(commonItem.getOpeDate());		// 運用日
		
		// SQL実行
		dbAccess.selectBySqlDefine(dbSelectList, SQLDEFKEY_GENE_FILE);
		
		// 結果を取得
		JBSbatCommonDBInterface dbMap = dbAccess.selectNext();
		
		// 取得できなかった場合
		if(null == dbMap)
		{
			// ログ出力（【エラー】ＤＢ未存在エラー）
			String[] msgParam = new String[]
			{ JBSbatAC_M_FILE_GENE_CTRL.TABLE_NAME, dbSelectList.getList().toString() };
			throw new JBSbatBusinessException(JPCBatchMessageConstant.EACB0250CE, msgParam);
		}
		
		// DBアクセスクラス　クローズ
		dbAccess.close();
		
		// ファイル名編集
		
		// ファイル識別格納配列
		String[] fileKbnArray = {commonItem.getSystemCode()				// システムコード
								, seikyYm								// 請求年月
								, commonItem.getOpeDate()				// 運用日
								, JCCBatCommon.getSysDateTimeStamp()	// システム日時
								, freeSet								// 自由設定
								, tajuNo};								// 多重番号
		
		// ファイル名編集部品実行
		String[] fileInfo = editFileItemName(fileNo, dbMap, fileKbnArray);
		
		// ファイルオープン（引数：ファイル名（フルパス）, 文字コード, 改行コード, 区切り文字）
		JBSbatBusinessFileUtil outFileObj = JCCBatCommon.createBusinessFileUtil(fileInfo[0], mojiCd, chgKaigyo(rowCd), fileInfo[1]);
		
		// 戻り値を設定
		ArrayList<Object> rtnValue = new ArrayList<Object>();
		
		rtnValue.add(fileInfo[0]);		// ファイル名（フルパス）
		rtnValue.add(fileInfo[1]);		// 区切り文字
		rtnValue.add(outFileObj);		// ファイルインスタンス
		
		return rtnValue;
	}
	
	/**
	 * ESB連携部品エラー出力処理を行います。
	 * <br>
	 * @param usecaseId ユースケースID
	 * @param rdCd リターンコード
	 * @param resultMap 処理結果マップ
	 * @param logPrint ログ出力部品
	 */
	public static void esbErrOutputPrc(String usecaseId, String rdCd, HashMap<Object, Object> resultMap, JBSbatLogPrintControl logPrint) throws Exception
	{
		String wkMsg = null;
		
		// エラー判定
		if(JCCBatchEsbInterface.RETURN_CODE_WARNING.equals(rdCd))
		{
			wkMsg = JACStrConst.ESB_MSG_WARNING;
		}
		else if(JCCBatchEsbInterface.RETURN_CODE_SINGLEDATA_ERR.equals(rdCd))
		{
			wkMsg = JACStrConst.ESB_MSG_SINGLEDATA_ERR;
		}
		else if(JCCBatchEsbInterface.RETURN_CODE_ITEM_RELATION_ERR.equals(rdCd))
		{
			wkMsg = JACStrConst.ESB_MSG_ITEM_RELATION_ERR;
		}
		else if(JCCBatchEsbInterface.RETURN_CODE_RELATION_ERR.equals(rdCd))
		{
			wkMsg = JACStrConst.ESB_MSG_RELATION_ERR;
		}
		else if(JCCBatchEsbInterface.RETURN_CODE_STATUSTRANS_ERR.equals(rdCd))
		{
			wkMsg = JACStrConst.ESB_MSG_STATUSTRANS_ERR;
		}
		else if(JCCBatchEsbInterface.RETURN_CODE_AUTHORITY_ERR.equals(rdCd))
		{
			wkMsg = JACStrConst.ESB_ERR_MSG_AUTHORITY_ERR;
		}
		else if(JCCBatchEsbInterface.RETURN_CODE_SELECT_UPDATE_AUTHORITY_ERR.equals(rdCd))
		{
			wkMsg = JACStrConst.ESB_MSG_SEL_UPD_AUTHORITY_ERR;
		}
		else if(JCCBatchEsbInterface.RETURN_CODE_UPDATE_AUTHORITY_ERR.equals(rdCd))
		{
			wkMsg = JACStrConst.ESB_MSG_UPD_AUTHORITY_ERR;
		}
		else
		{
			wkMsg = JACStrConst.ESB_MSG_SYSTEMERR;
		}
		
		StringBuffer errMsg = new StringBuffer();
		errMsg.append(wkMsg);
		errMsg.append(resultMap.toString());
		
		// ログ出力
		String[] msgParam = new String[]
		{ usecaseId, rdCd, errMsg.toString()};
		logPrint.printBusinessErrorLog(JPCBatchMessageConstant.EACB0900CW, msgParam);
	}
	
	/**
	 * 料金項目コードを基に税区を設定します。
	 * <br>
	 * @param arg0 料金項目コード
	 * @return taxAreaPrc 税区
	 */
	public static String getTaxAreaPrc(String arg0) 
	{
		// 税区
		String taxAreaPrc = JACStrConst.KARA_MOJI;
		
		// 料金項目コードの下3桁目を取得
		int target = 0;
		try
		{
			target = Integer.parseInt(arg0.substring(arg0.length() - 3, arg0.length() - 2));
		}
		catch (NumberFormatException e)
		{
			// 数値以外の場合
			return taxAreaPrc;
		}
		
		// 税区を設定する
		switch(target)
		{
		case 0:
			// 外税
			taxAreaPrc = TAX_KBN1;
			break;
		case 1:
			// レンタル
			taxAreaPrc = TAX_KBN4;
			break;
		case 2:
			// 消費税
			taxAreaPrc = TAX_KBN4;
			break;
		case 5:
			// 非課税
			taxAreaPrc = TAX_KBN3;
			break;
		case 6:
			// 内税
			taxAreaPrc = TAX_KBN2;
			break;
		case 7:
			// 利用不可期間減額
			taxAreaPrc = TAX_KBN4;
			break;
		case 8:
			// マイナス内訳
			taxAreaPrc = TAX_KBN4;
			break;
		case 9:
			// 調整
			taxAreaPrc = TAX_KBN4;
			break;
		default:
		}
		
		return taxAreaPrc;
	}
	
	/**
	 * 埋め込み文字を指定されたマップにて置き換えます。
	 * <br>
	 * @param arg0 対象文字列
	 * @param map 変換用マップ
	 * @return String 編集後の文字列
	 */
	public static String ckanUmeMojiHanyo(String arg0, HashMap<String, String>map) 
	{
		// 対象文字列 ＝ null または 対象文字列．サイズ ＝ 0 の場合
		if(!JACBatCommon.isNull(JPCUtilCommon.trim(arg0)))
		{
			// 文字列変換処理
			for(Map.Entry<String, String> etry : map.entrySet())
			{
				arg0 = arg0.replace(etry.getKey(), etry.getValue());
			}
		}
		return arg0;
	}
	
	/**
	 * 指定した文字列が上限値と下限値の有効範囲内か判断する。（文字列比較）
	 * <BR>
	 * @param upper 上限値
	 * @param upperFlg 上限値と同値を含むかどうか（trueで上限値と同値を含む）
	 * @param lower 下限値
	 * @param lowerFlg 下限値と同値を含むかどうか（trueで下限値と同値を含む）
	 * @param para  指定文字列
	 * @param flg 指定文字列が数値として扱われるデータか判断する。（1:数値、2:文字列（可変）、3:文字列（年月日）、4:文字列（時分秒））
	 * @return boolean true :有効範囲内
	 * 					false:有効範囲外
 	 * @throws Exception
	 */
	public static boolean rangeCheck(String upper, boolean upperFlg, String lower, boolean lowerFlg,
			String para, String flg) throws Exception
	{
		// 引数チェック
		if ((upper == null) || (upper.equals("")))
		{
			throw new IllegalArgumentException("引数が不正です。");
		}
		if ((lower == null) || (lower.equals("")))
		{
			throw new IllegalArgumentException("引数が不正です。");
		}
		if ((flg == null) || (flg.equals("")))
		{
			throw new IllegalArgumentException("引数が不正です。");
		}
		if (para == null)
		{
			return false;
		}
		para = para.trim();
		if (para.equals(""))
		{
			return false;
		}

		// フラグから桁埋めの形式を判定する
		// 数値の場合
		if ("1".equals(flg))
		{
			// 全体の桁数を合わせる（空白左詰め）
			if (upper.length() >= lower.length())
			{
				while (upper.length() != lower.length())
				{
					lower = " ".concat(lower);
				}
			}
			else
			{
				throw new Exception("上限値と下限値が不正です。");
			}
			if (upper.length() >= para.length())
			{
				while (upper.length() != para.length())
				{
					para = " ".concat(para);
				}
			}
			else
			{
				return false;
			}
		}
		// 文字列（可変）の場合
		else if ("2".equals(flg))
		{
			// 全体の桁数を合わせる（空白右詰め）
			if (upper.length() >= lower.length())
			{
				while (upper.length() != lower.length())
				{
					lower = lower.concat(" ");
				}
			}
			else
			{
				while (upper.length() != lower.length())
				{
					upper = upper.concat(" ");
				}
			}
			if (upper.length() >= para.length())
			{
				while (upper.length() != para.length())
				{
					para = para.concat(" ");
				}
			}
			else
			{
				// upperとlowerの桁合わせを同じwhileで行っても構わないが、一応分別。
				while (upper.length() != para.length())
				{
					upper = upper.concat(" ");
				}
				while (lower.length() != para.length())
				{
					lower = lower.concat(" ");
				}
			}
		}
		// それ以外の場合
		else
		{
			// 指定文字列の桁数を合わせる（空白左詰め）
			if (upper.length() != para.length()
					|| lower.length() != para.length())
			{
				throw new Exception("年月日または時分秒のデータが不正です。");
			}
		}

		// 上限値下限値不正チェック
		if (0 > upper.compareTo(lower))
		{
			throw new Exception("上限値と下限値が不正です。");
		}

		// 有効範囲チェック
		// 下限値チェック（同値含む）
		if (lowerFlg && 0 > para.compareTo(lower))
		{
			return false;
		}
		// 下限値チェック（同値含まない）
		if (!lowerFlg && 0 >= para.compareTo(lower))
		{
			return false;
		}
		// 上限値チェック（同値含む）
		if (upperFlg && 0 < para.compareTo(upper))
		{
			return false;
		}
		// 上限値チェック（同値含まない）
		if (!upperFlg && 0 <= para.compareTo(upper))
		{
			return false;
		}
		return true;
	}
	
	/**
	 * 時間の加減算を行います。
	 * <br>
	 * @param arg0 対象日付(yyyyMMddHHmmssSSS)
	 * @param arg1 加減算値
	 * @return String 加減算された日付
	 * @throws ParseException 
	 */
	public static String addHour(String arg0, int arg1) throws ParseException 
	{

		String addResult = null;
		
		SimpleDateFormat form = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		Calendar calender = Calendar.getInstance();
		calender.setTime(form.parse(arg0));
		calender.add(Calendar.HOUR, arg1);
		
		addResult = form.format(calender.getTime());
		
		return addResult;
	}

}
