/*********************************************************************
 *	All Rights reserved,Copyright (c) K-Opticom
 **********************************************************************
 *＜プログラム内容＞
 *	システム名		：eo顧客基幹システム
 *	モジュール名	：JPCStringUtil
 *	ソースファイル名：JPCStringUtil.java
 *	作成者			：富士通
 *	日付			：2011年02月16日
 *＜機能概要＞
 *	文字列書式の変換を行う共通機能を提供する。
 *＜修正履歴＞
 *	バージョン	修正日		修正者		修正内容
 *	v1.00.00	2011/02/16	FJ			新規作成
 *	v4.00.00	2012/10/02	FJ)笹川		IT1-2012-0001061(指定対象外文字列変換に対する修正)
 *  v54.00.00   2021/07/29   FJ)西窪    【ANK-4092-00-00】 CX戦略WG方針対応STEP2
 *
 **********************************************************************/
package eo.common.util;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

/**
 * 文字列書式の変換を行うクラスです。<p>
 * <br>
 * @author 富士通
 */
public class JPCFomatString extends JPCCommonUtil 
{
	/** 
	 * 年月日書式(yyyyMMdd) 
	 */
	private static final String FMT_YMD = "yyyyMMdd";

	/** 
	 * 年月日編集書式(yyyy/MM/dd) 
	 */
	private static final String EDIT_YMD = "yyyy/MM/dd";

	/** 
	 * 日時書式(yyyyMMddHHmmssSSS) 
	 * */
	private static final String FMT_YMDHMSS = "yyyyMMddHHmmssSSS";

	/** 
	 * 日時編集書式(yyyy/MM/dd HH:mm:ss.SSS) 
	 */
	private static final String EDIT_YMDHMSS = "yyyy/MM/dd HH:mm:ss.SSS";

	/** 
	 * 日時書式(yyyyMMddHHmmss) 
	 * */
	private static final String FMT_YMDHMS = "yyyyMMddHHmmss";

	/** 
	 * 日時編集書式(yyyy/MM/dd HH:mm:ss) 
	 * */
	private static final String EDIT_YMDHMS = "yyyy/MM/dd HH:mm:ss";

	/** 
	 * 日時書式(yyyyMMddHHmm) 
	 */
	private static final String FMT_YMDHM = "yyyyMMddHHmm";

	/** 
	 * 日時編集書式(yyyy/MM/dd HH:mm) 
	 */
	private static final String EDIT_YMDHM = "yyyy/MM/dd HH:mm";

	/** 
	 * 時分書式(HHmm) 
	 */
	private static final String FMT_HM = "HHmm";

	/** 
	 * 時分編集書式(HH:mm) 
	 */
	private static final String EDIT_HM = "HH:mm";

	/** 
	 * 数値の編集書式(カンマ区切り) 
	 */
	private static final String FMT_NUM = ",###";

	/** 
	 * 年月日書式(yyyyMMdd)の桁数 
	 */
	private static final int YMD = 8;

	/** 
	 * 日時書式(yyyyMMddHHmmssSSS)の桁数 
	 */
	private static final int YMDHMSS = 17;

	/** 
	 * 日時書式(yyyyMMddHHmmss)の桁数 
	 */
	private static final int YMDHMS = 14;

	/** 
	 * 日時書式(yyyyMMddHHmm)の桁数 
	 */
	private static final int YMDHM = 12;

	/** 
	 * 時分書式(HHmm)の桁数 
	 */
	private static final int HM = 4;

	/** 
	 * マスク文字 
	 */
	private static final String MASK = "*";

	/** 
	 * 開始文字位置 
	 */
	private static final int STARTMOJI = 1;

	/** 
	 * 電話番号用桁数(XX-XXXX-XXXX) 
	 */
	private static final int TELNO_10 = 10;

	/** 
	 * 電話番号用桁数(XXX-XXXX-XXXX) 
	 */
	private static final int TELNO_11 = 11;

	/** 
	 * 電話番号用桁数(XXXX-XXXX-XXXX) 
	 */
	private static final int TELNO_12 = 12;

	/** 
	 * ハイフン 
	 */
	private static final String HYHUN = "-";

	/** 
	 * 年月書式(yyyyMM) 
	 */
	private static final String FMT_YM = "yyyyMM";

	/** 
	 * 年月日編集書式(yyyy/MM) 
	 */
	private static final String EDIT_YM = "yyyy/MM";

	/** 
	 * 年月書式(yyyyMM)の桁数 
	 */
	private static final int YM = 6;

	/** 
	 * 郵便番号(XXX-XXXX) 
	 */
	private static final int PCD = 7;

	/** 
	 * 住所コード(XX-XXX-XXX-XXX) 
	 */
	private static final int AD_CD = 11;

	/**
	 * 年月書式(yyyy/MM)の編集を行います。
	 * <br>
	 * @param arg0 年月日書式に編集する文字列(yyyyMM)
	 * @return String 年月日書式に編集された文字列(yyyy/MM)
	 */
	public static String formatYears(String arg0) 
	{
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		if(!JPCFomatString.isValidParameter(arg0, YM)) 
		{
			return arg0;
		}

		return toFormatDate(arg0, FMT_YM, EDIT_YM);
	}


	/**
	 * 郵便番号のハイフン処理を行います。
	 * <br>
	 * @param arg0 	編集対象の郵便番号
	 * @return String 書式編集された郵便番号
	 */
	public static String hyhunPcd(String arg0) 
	{
		// nullチェックを行う
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		// 桁数チェックを行う
		if(!JPCFomatString.isValidParameter(arg0, PCD)) 
		{
			return arg0;
		}

		return arg0.substring(0, 3) + HYHUN + arg0.substring(3, 7);
	}

	/**
	 * 住所コードのハイフン処理を行います。
	 * <br>
	 * @param arg0 	編集対象の住所コード
	 * @return String 書式編集された住所コード
	 */
	public static String hyhunAdCd(String arg0) 
	{
		// nullチェックを行う
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		// 桁数チェックを行う
		if(!JPCFomatString.isValidParameter(arg0, AD_CD)) 
		{
			return arg0;
		}

		return arg0.substring(0, 2) + HYHUN + arg0.substring(2, 5) + HYHUN + arg0.substring(5, 8) + HYHUN + arg0.substring(8, 11);
	}

	/**
	 * 年月日書式(yyyy/MM/dd)の編集を行います。
	 * <br>
	 * @param arg0 年月日書式に編集する文字列(yyyyMMdd)
	 * @return String 年月日書式に編集された文字列(yyyy/MM/dd)
	 */
	public static String formatDate(String arg0) 
	{
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		if(!JPCFomatString.isValidParameter(arg0, YMD)) 
		{
			return arg0;
		}

		return toFormatDate(arg0, FMT_YMD, EDIT_YMD);
	}

	/**
	 * 日時書式(yyyy/MM/dd HH:mm:ss.SSS)の編集を行います。
	 * <br>
	 * @param arg0 日時書式に編集する文字列(yyyyMMddHHmmssSSS)
	 * @return String 日時書式に編集された文字列(yyyy/MM/dd HH:mm:ss.SSS)
	 */
	public static String formatDatetimeSSS(String arg0) 
	{
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		if(!JPCFomatString.isValidParameter(arg0, YMDHMSS)) 
		{
			return arg0;
		}

		return toFormatDate(arg0, FMT_YMDHMSS, EDIT_YMDHMSS);
	}
	
	// ANK-4092-00-00 ADD START
	/**
	 * 日時書式(yyyyMMddHHmmssSSS)の編集を行います。
	 * <br>
	 * @param arg0 日時書式に編集する文字列(yyyy/MM/dd HH:mm:ss.SSS)
	 * @return String 日時書式に編集された文字列(yyyyMMddHHmmssSSS)
	 */
	public static String formatDatetimeSSSReverse(String arg0) 
	{
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		if(!JPCFomatString.isValidParameter(arg0, 23)) 
		{
			return arg0;
		}

		return toFormatDate(arg0, EDIT_YMDHMSS, FMT_YMDHMSS);
	}
	// ANK-4092-00-00 ADD END

	/**
	 * 日時書式(yyyy/MM/dd HH:mm:ss)の編集を行います。
	 * <br>
	 * @param arg0 日時書式に編集する文字列(yyyyMMddHHmmss)
	 * @return String 日時書式に編集された文字列(yyyy/MM/dd HH:mm:ss)
	 */
	public static String formatDatetimeSS(String arg0) 
	{
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		if(!JPCFomatString.isValidParameter(arg0, YMDHMS)) 
		{
			return arg0;
		}

		return toFormatDate(arg0, FMT_YMDHMS, EDIT_YMDHMS);
	}

	/**
	 * 日時書式(yyyy/MM/dd HH:mm)の編集を行います。
	 * <br>
	 * @param arg0 日時書式に編集する文字列(yyyyMMddHHmm)
	 * @return String 日時書式に編集された文字列(yyyy/MM/dd HH:mm)
	 */
	public static String formatDatetimeMM(String arg0) 
	{
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		if(!JPCFomatString.isValidParameter(arg0, YMDHM)) 
		{
			return arg0;
		}

		return toFormatDate(arg0, FMT_YMDHM, EDIT_YMDHM);
	}

	/**
	 * 時刻書式(HH:mm)の編集を行います。
	 * <br>
	 * @param arg0 時刻書式に編集する文字列(HHmm)
	 * @return String 時刻書式に編集された文字列(HH:mm)
	 */
	public static String formatTime(String arg0) 
	{
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		if(!JPCFomatString.isValidParameter(arg0, HM)) 
		{
			return arg0;
		}

		return toFormatDate(arg0, FMT_HM, EDIT_HM);
	}

	/**
	 * 数値書式(カンマ区切り)の編集を行います。
	 * <br>
	 * @param arg0 カンマ区切りに編集する文字列
	 * @return String 数値書式(カンマ区切り)に編集された文字列
	 */
	public static String formatNumber(String arg0) 
	{
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		try 
		{
			String pattern = getNumberPattern(arg0);

			DecimalFormat instance = new DecimalFormat(pattern);

			return instance.format(new Double(arg0));
		}
		catch (NumberFormatException nfe) 
		{
			return arg0;
		}
	}

	/**
	 * 文字列を*でマスクします。
	 * <br>
	 * @param arg0 編集する文字列
	 * @return String 「*」で編集された文字列
	 * @throws Exception 文字列マスク編集処理（マスク文字列指定）にて、例外が発生した場合
	 */
	public static String forMask(String arg0) 
	{
		return forMaskMarc(arg0, MASK);
	}

	/**
	 * 指定された文字列をマスクする文字でマスクします。
	 * <br>
	 * @param arg0 編集する文字列
	 * @param arg1 マスク文字
	 * @return String 編集された文字列
	 */
	public static String forMaskMarc(String arg0, String arg1) 
	{
		// 編集する文字列の桁数
		int size = 0;

		if(arg0 != null) 
		{
			size = arg0.length();
		}

		return editCharStrMask(arg0, arg1, STARTMOJI, size);
	}

	/**
	 * 指定された文字列、開始文字位置、文字数でマスクします。
	 * <br>
	 * @param arg0 編集する文字列
	 * @param arg1 マスク文字
	 * @param arg2 開始文字位置
	 * @param arg3 文字数
	 * @return String 編集された文字列
	 */
	public static String editCharStrMask(String arg0, String arg1, int arg2, int arg3) 
	{
		// 編集文字列が空白の場合、何もしない
		if(JPCFomatString.isNull(arg0))
		{
			return arg0;
		}

		// マスク文字が空白の場合、何もしない
		if(JPCFomatString.isNull(arg1))
		{
			return arg0;
		}

		// 開始文字位置が0以下の場合、例外をスローする
		if(arg2 <= 0)
		{
			throw new IllegalArgumentException("開始文字位置が0以下です。");
		}

		// 文字数0の場合、何もしない
		if(arg3 == 0)
		{
			return arg0;
		}

		// 文字数が0未満の場合、例外をスローする
		if(arg3 < 0)
		{
			throw new IllegalArgumentException("文字数がマイナス値です。");
		}

		// 開始文字位置が編集文字列長より大きい場合、例外をスローする
		if(arg0.length() < arg2)
		{
			throw new IllegalArgumentException("計算結果がマイナス値です。");
		}

		String strNoMaskLeft = null;
		String strNoMaskMid = null;
		String strNoMaskRight = null;

		// 開始文字位置より左側の文字列を取得
		if(1 == arg2)
		{
			strNoMaskLeft = "";
		}
		else
		{
			strNoMaskLeft = arg0.substring(0, arg2 - 1);
		}

		// 開始文字位置〜開始文字位置＋文字数の文字列を取得
		// 開始文字位置＋文字数より右側の文字列を取得
		if(arg0.length() <= arg2 - 1 + arg3)
		{
			strNoMaskMid = arg0.substring(arg2 - 1);
			strNoMaskRight = "";
		}
		else
		{
			strNoMaskMid = arg0.substring(arg2 - 1, arg2 - 1 + arg3);
			strNoMaskRight = arg0.substring(arg2 - 1 + arg3);
		}

		// 開始文字位置〜開始文字位置＋文字数の文字列をマスクする
		StringBuffer strBufMask = new StringBuffer();
		for(int i = 1; i <= strNoMaskMid.length(); i++)
		{
			strBufMask.append(arg1);
		}
		String strMask = strBufMask.toString();

		// マスク後の文字列を返却する
		return strNoMaskLeft + strMask + strNoMaskRight;
	}

	/**
	 * 電話番号に-記号を付与します。（XX-XXXX-XXXX）
	 * <br>
	 * @param arg0 変換する電話番号
	 * @return String 変換された電話番号
	 */
	public static String formatTelNoAdd1(String arg0) 
	{
		// nullチェックを行う
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		// 桁数チェックを行う
		if(!JPCFomatString.isValidParameter(arg0, TELNO_10)) 
		{
			return arg0;
		}

		// ハイフン編集を行う
		return hyhunTelNo(arg0, TELNO_10);
	}

	/**
	 * 電話番号に-記号を付与します。（XXX-XXXX-XXXX）
	 * <br>
	 * @param arg0 変換する電話番号
	 * @return String 変換された電話番号
	 */
	public static String formatTelNoAdd2(String arg0) 
	{
		// nullチェックを行う
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		// 桁数チェックを行う
		if(!JPCFomatString.isValidParameter(arg0, TELNO_11)) 
		{
			return arg0;
		}

		// ハイフン編集を行う
		return hyhunTelNo(arg0, TELNO_11);
	}

	/**
	 * 電話番号に-記号を付与します。（XXXX-XXXX-XXXX）
	 * <br>
	 * @param arg0 変換する電話番号
	 * @return String 変換された電話番号
	 */
	public static String formatTelNoAdd3(String arg0) 
	{
		// nullチェックを行う
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		// 桁数チェックを行う
		if(!JPCFomatString.isValidParameter(arg0, TELNO_12)) 
		{
			return arg0;
		}

		// ハイフン編集を行う
		return hyhunTelNo(arg0, TELNO_12);
	}

	/**
	 * 電話番号の-記号を削除します。
	 * <br>
	 * @param arg0 変換する電話番号
	 * @return String 変換された電話番号
	 */
	public static String formatTelNoDel(String arg0) 
	{
		// nullチェックを行う
		if(JPCFomatString.isNull(arg0)) 
		{
			return arg0;
		}

		return arg0.replace(HYHUN, "");
	}

	/**
	 * 日付オブジェクトを指定された形式の文字列に編集します。
	 * <br>
	 * @param arg0 編集する日付オブジェクト
	 * @param arg1 java.util.Date型の日付書式
	 * @param arg2 編集する文字列の日付書式
	 * @return String 指定された形式に編集された文字列
	 */
	private static String toFormatDate(String arg0, String arg1, String arg2) 
	{
		try 
		{
			SimpleDateFormat instance = new SimpleDateFormat(arg1);

			return new SimpleDateFormat(arg2).format(instance.parse(arg0));

		}
		catch (ParseException pe) 
		{
			return arg0;
		}
	}

	/**
	 * 文字列の形式に従い、数字列の書式を取得します。
	 * <br>
	 * @param arg0 数値書式編集する文字列
	 * @return String 数値書式編集された文字列
	 */
	private static String getNumberPattern(String arg0) 
	{
		int idx = arg0.indexOf(".");

		if (0 > idx) 
		{
			return FMT_NUM;
		}

		StringBuffer ret = new StringBuffer();

		ret.append(FMT_NUM);

		ret.append(".");

		String str = arg0.substring(idx + 1);

		for (int i = 0; i < str.length(); i++) 
		{
			ret.append("#");
		}

		return ret.toString();
	}

	/**
	 * 電話番号のハイフン処理を行います。
	 * <br>
	 * @param arg0 	電話番号書式する電話番号
	 * @param arg1 電話番号の桁数
	 * @return String 電話番号書式された電話番号
	 */
	private static String hyhunTelNo(String arg0, int arg1) 
	{
		StringBuffer strBuf = new StringBuffer();

		for(int i = 0; i < arg1; i++) 
		{
			if(8 == arg1 - i || 4 == arg1 - i) 
			{
				strBuf.append(HYHUN);
			}

			strBuf.append(arg0.substring(i, i+1));
		}

		return strBuf.toString();
	}
}
