/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JZMAdEdit
*	ソースファイル名：JZMAdEdit.java
*	作成者			：富士通
*	日付			：2012年02月29日
*＜機能概要＞
*	住所編集を行います。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v3.00   	2012/02/29	FJ) 岩元	新規作成
*	v3.00		2012/02/29	FJ) 岩元	【SGY-2012-0000015】新規作成
*
**********************************************************************/

package eo.common.util;

/**
 * 7分割住所を任意の箇所で結合して返します。<p>
 * <br>
 * @author 富士通
 */
public class JZMAdEdit extends JZMAdOutputEdit
{

	/** 住所1 都道府県名 */
	private String inAd1 = null;
	
	/** 住所2 市区町村名 */
	private String inAd2 = null;

	/** 住所3 大字通称名 */
	private String inAd3 = null;

	/** 住所4 字丁目名 */
	private String inAd4 = null;

	/** 住所5 番地号 */
	private String inAd5 = null;

	/** 住所6 住所補記・建物名 */
	private String inAd6 = null;

	/** 住所7 住所補記・部屋番号 */
	private String inAd7 = null;
	
	/** 住所5 字丁目編集オブジェクト */
	private StringBuilder workAd5 = null;
	

	/** 住所1の桁数チェック結果 */
	private boolean isAd1LengthOver = false;
	
	/** 住所2の桁数チェック結果 */
	private boolean isAd2LengthOver = false;
	
	/** 住所3の桁数チェック結果 */
	private boolean isAd3LengthOver = false;
	
	/** 住所4の桁数チェック結果 */
	private boolean isAd4LengthOver = false;
	
	/** 住所5の桁数チェック結果 */
	private boolean isAd5LengthOver = false;
	
	/** 住所6の桁数チェック結果 */
	private boolean isAd6LengthOver = false;
	
	/** 住所7の桁数チェック結果 */
	private boolean isAd7LengthOver = false;
	
	/**
	 * 住所1 都道府県名を取得する。
	 * @return 都道府県名
	 */
	public String getAd1()
	{
		return inAd1;
	}

	/**
	 * 住所1 都道府県名を設定する。
	 * @param ad1 都道府県名
	 */
	public void setAd1(String ad1)
	{
		this.inAd1 = trimSpace(ad1);
		if(isOverLength(this.inAd1, AD1_LEN))
		{
			this.inAd1 = null;
			isAd1LengthOver = true;
		}
	}


	/**
	 * 住所2 市区町村名を取得する。
	 * @return 市区町村名
	 */
	public String getAd2()
	{
		return inAd2;
	}

	/**
	 * 住所2 市区町村名を設定する。
	 * @param ad2 市区町村名
	 */
	public void setAd2(String ad2)
	{
		this.inAd2 = trimSpace(ad2);
		if(isOverLength(this.inAd2, AD2_LEN))
		{
			this.inAd2 = null;
			isAd2LengthOver = true;
		}
	}


	/**
	 * 住所3 大字通称名を取得する。
	 * @return 大字通称名
	 */
	public String getAd3()
	{
		return inAd3;
	}


	/**
	 * 住所3 大字通称名を設定する。
	 * @param ad3 大字通称名
	 */
	public void setAd3(String ad3)
	{
		this.inAd3 = trimSpace(ad3);
		if(isOverLength(this.inAd3, AD3_LEN))
		{
			this.inAd3 = null;
			isAd3LengthOver = true;
		}
	}

	/**
	 * 住所4 字丁目名を取得する。
	 * @return 字丁目名
	 */
	public String getAd4()
	{
		return inAd4;
	}


	/**
	 * 住所4 字丁目名を設定する。
	 * @param ad4 字丁目名
	 */
	public void setAd4(String ad4)
	{
		this.inAd4 = trimSpace(ad4);
		if(isOverLength(this.inAd4, AD4_LEN))
		{
			this.inAd4 = null;
			isAd4LengthOver = true;
		}
	}



	/**
	 * 住所5 番地号を取得する。
	 * @return 番地号
	 */
	public String getAd5()
	{
		return inAd5;
	}

	/**
	 * 住所5 番地号を設定する。
	 * @param ad5 番地号
	 */
	public void setAd5(String ad5)
	{
		this.inAd5 = trimSpace(ad5);
		if(isOverLength(this.inAd5, AD5_YOSE_LEN))
		{
			this.inAd5 = null;
			isAd5LengthOver = true;
		}
	}

	/**
	 * 住所6 住所補記1を取得する。
	 * @return 住所補記1
	 */
	public String getAd6()
	{
		return inAd6;
	}

	/**
	 * 住所6 住所補記1を設定する。
	 * @param ad6 住所補記・建物名
	 */
	public void setAd6(String ad6)
	{
		this.inAd6 = trimSpace(ad6);
		if(isOverLength(this.inAd6, AD6_LEN))
		{
			this.inAd6 = null;
			isAd6LengthOver = true;
		}
	}


	/**
	 * 住所7 住所補記2を取得する。
	 * @return 住所補記2
	 */
	public String getAd7()
	{
		return inAd7;
	}

	/**
	 * 住所7 住所補記2を設定する。
	 * @param ad7 住所補記・部屋番号
	 */
	public void setAd7(String ad7)
	{
		this.inAd7 = trimSpace(ad7);
		if(isOverLength(this.inAd7, AD7_LEN))
		{
			this.inAd7 = null;
			isAd7LengthOver = true;
		}
	}
	
	/**
	 * 都道府県名の桁数オーバー判定結果
	 * @return 判定結果
	 */
	public boolean isAd1LengthOver()
	{
		return isAd1LengthOver;
	}

	/**
	 * 市区町村名の桁数オーバー判定結果
	 * @return 判定結果
	 */
	public boolean isAd2LengthOver()
	{
		return isAd2LengthOver;
	}

	/**
	 * 大字通称名の桁数オーバー判定結果
	 * @return 判定結果
	 */
	public boolean isAd3LengthOver()
	{
		return isAd3LengthOver;
	}

	/**
	 * 字丁目名の桁数オーバー判定結果
	 * @return 判定結果
	 */
	public boolean isAd4LengthOver()
	{
		return isAd4LengthOver;
	}

	/**
	 * 番地号の桁数オーバー判定結果
	 * @return 判定結果
	 */
	public boolean isAd5LengthOver()
	{
		return isAd5LengthOver;
	}

	/**
	 * 住所補記・建物名の桁数オーバー判定結果
	 * @return 判定結果
	 */
	public boolean isAd6LengthOver()
	{
		return isAd6LengthOver;
	}

	/**
	 * 住所補記・部屋番号の桁数オーバー判定結果
	 * @return 判定結果
	 */
	public boolean isAd7LengthOver()
	{
		return isAd7LengthOver;
	}

	/**
	 * すべての住所情報を取得する。
	 * @return 住所1〜住所7の配列
	 */
	public String[] getAdAll()
	{
		return new String[]{inAd1,  inAd2, inAd3, inAd4, inAd5, inAd6, inAd7};
	}

	/**
	 * 住所情報を設定する。
	 * @param ad1 都道府県名
	 * @param ad2 市区町村名
	 * @param ad3 大字通称名
	 * @param ad4 字丁目名
	 * @param ad5 番地号
	 * @param ad6 住所補記1
	 * @param ad7 住所補記2
	 */
	private void setAdAll(String ad1, String ad2, String ad3, String ad4, String ad5, String ad6, String ad7)
	{
		setAd1(ad1);
		setAd2(ad2);
		setAd3(ad3);
		setAd4(ad4);
		setAd5(ad5);
		setAd6(ad6);
		setAd7(ad7);
		if(isAd1LengthOver || isAd2LengthOver || isAd3LengthOver || isAd4LengthOver || isAd5LengthOver || isAd6LengthOver || isAd7LengthOver)
		{
			clear();
		}
	}
	
	/**
	 * 文字数が指定数より大きいかを判定します。
	 * @param ad 文字列
	 * @param compLen 指定数
	 * @return 判定結果
	 */
	private boolean isOverLength(String ad, int compLen)
	{
		if(isNull(ad))
		{
			return false;
		}
		return ad.length() > compLen;
	}
	
	
	/**
	 * 設定された住所情報をnullにします。
	 */
	public void clear()
	{
		inAd1 = null;
		inAd2 = null;
		inAd3 = null;
		inAd4 = null;
		inAd5 = null;
		inAd6 = null;
		inAd7 = null;
		workAd5 = null;
		isAd1LengthOver = false;
		isAd2LengthOver = false;
		isAd3LengthOver = false;
		isAd4LengthOver = false;
		isAd5LengthOver = false;
		isAd6LengthOver = false;
		isAd7LengthOver = false;
	}

	/**
	 * コンストラクタ
	 * @param ad1 都道府県名
	 * @param ad2 市区町村名
	 * @param ad3 大字通称名
	 * @param ad4 字丁目名
	 * @param ad5 番地号
	 * @param ad6 住所補記・建物名
	 * @param ad7 住所補記・部屋番号
	 */
	public JZMAdEdit(String ad1, String ad2, String ad3, String ad4, String ad5, String ad6, String ad7)
	{

		setAdAll(ad1, ad2, ad3, ad4, ad5, ad6, ad7);
	}
	
	/**
	 * コンストラクタ
	 * @param ad1 都道府県名
	 * @param ad2 市区町村名
	 * @param ad3 大字通称名
	 * @param ad4 字丁目名
	 * @param ad5 番地号
	 * @param ad6 住所補記・建物名
	 * @param ad7 住所補記・部屋番号
	 * @param isDivide 番地号寄せ分割実行判定
	 */
	public JZMAdEdit(String ad1, String ad2, String ad3, String ad4, String ad5, String ad6, String ad7, boolean isDivide)
	{
		
		setAdAll(ad1, ad2, ad3, ad4, ad5, ad6, ad7);
		
		if(isDivide)
		{
			divideBnchigoYose();
		}
	}

	/**
	 * 番地号寄せ分割編集処理
	 */
	public void divideBnchigoYose()
	{
		if(isNull(inAd5))
		{
			clear();
			return;
		}
		
		inAd1 = nullToBlank(inAd1);
		inAd2 = nullToBlank(inAd2);
		inAd3 = nullToBlank(inAd3);
		inAd4 = nullToBlank(inAd4);
		
		
		workAd5 = new StringBuilder();
		workAd5.append(inAd5);
		
		if(isNull(inAd1))
		{
			if(inAd1.length() != inAd2.length() + inAd3.length() + inAd4.length())
			{
				clear();
				return;
			}
			int max = AD1_LEN + AD2_LEN + AD3_LEN + AD4_LEN + AD5_LEN;
			if(max < workAd5.length())
			{
				clear();
				return;
			}
			int min = AD1_LEN;
			if(workAd5.length() <= min)
			{
				clear();
				return;
			}
			
			inAd1 = getWorkAd5KamiMoji(AD1_LEN);
		}
		
		inAd5 = getWorkAd5ShimoMoji(AD5_LEN);
		
		if(workAd5.length() == 0)
		{
			return;
		}
		
		if(isNull(inAd2))
		{

			if(inAd2.length() != inAd3.length() + inAd4.length())
			{
				clear();
				return;
			}
			
			int max = AD2_LEN + AD3_LEN + AD4_LEN;
			if(max < workAd5.length())
			{
				clear();
				return;
			}
			inAd2 = getWorkAd5KamiMoji(AD2_LEN);
		}

		if(workAd5.length() == 0)
		{
			return;
		}
		
		if(isNull(inAd3))
		{
			if(inAd3.length() != inAd4.length())
			{
				clear();
				return;
			}
			int max = AD3_LEN + AD4_LEN;
			if(max < workAd5.length())
			{
				clear();
				return;
			}
			inAd3 = getWorkAd5KamiMoji(AD3_LEN);
		}

		if(workAd5.length() == 0)
		{
			return;
		}
		
		if(isNull(inAd4))
		{
			int max = AD4_LEN;
			if(max < workAd5.length())
			{
				clear();
				return;
			}
			inAd4 = getWorkAd5KamiMoji(AD4_LEN);
		}
	}
		
	/**
	 * 住所5 番地号の上から指定文字数取得します。
	 * @param mojiCnt 文字数
	 * @return 取得文字列
	 */
	private String getWorkAd5KamiMoji(int mojiCnt)
	{
		int i = checkMojiCnt(mojiCnt);
		String rtn = workAd5.substring(0, i);
		workAd5.delete(0, i);
		return rtn;
	}
	
	/**
	 * 住所5 番地号の下から指定文字数取得します。
	 * @param mojiCnt 文字数
	 * @return 取得文字列
	 */
	private String getWorkAd5ShimoMoji(int mojiCnt)
	{
		int i = checkMojiCnt(mojiCnt);
		String rtn = workAd5.substring(workAd5.length() - i);
		workAd5.delete(workAd5.length() - i, workAd5.length());
		return rtn;
	}
	
	/**
	 * 住所5 番地号から取得できるIndexを取得します。
	 * @param mojiCnt 指定文字数
	 * @return 指定文字数 または 指定可能な最大文字数
	 */
	private int checkMojiCnt(int mojiCnt)
	{
		int i = mojiCnt;
		if(workAd5.length() < mojiCnt)
		{
			i = workAd5.length();
		}
		return i;
	}
	
	/**
	 * 住所１から順に指定した値まで連結し返します。
	 * @param kamiIndex 指定値
	 * @return 連結された住所（半角スペースあり）
	 */
	public String getAdKamiHankakuSpace(int kamiIndex)
	{
		return getAdKamiIndex(kamiIndex,  true,  false);
	}

	/**
	 * 住所１から順に指定した値まで連結し返します。
	 * @param kamiIndex 指定値
	 * @return 連結された住所（全角スペースあり）
	 */
	public String getAdKamiZenkakuSpace(int kamiIndex)
	{
		return getAdKamiIndex(kamiIndex,  false,  true);
	}

	/**
	 * 住所１から順に指定した値まで連結し返します。
	 * @param kamiIndex 指定値
	 * @return 連結された住所
	 */
	public String getAdKami(int kamiIndex)
	{
		return getAdKamiIndex(kamiIndex,  false,  false);
	}
	
	/**
	 * 住所１〜７の上指定値から下指定値まで順に連結し返します。
	 * @param kamiIndex 上指定値
	 * @param shimoIndex 下指定値
	 * @return 連結された住所（半角スペースあり）
	 */
	public String getAdNakaHankakuSpace(int kamiIndex,  int shimoIndex)
	{
		return getAdNakaIndex(kamiIndex,  shimoIndex,  true,  false);
	}

	/**
	 * 住所１〜７の上指定値から下指定値まで順に連結し返します。
	 * @param kamiIndex 上指定値
	 * @param shimoIndex 下指定値
	 * @return 連結された住所（全角スペースあり）
	 */
	public String getAdNakaZenkakuSpace(int kamiIndex,  int shimoIndex)
	{
		return getAdNakaIndex(kamiIndex,  shimoIndex,  false,  true);
	}

	/**
	 * 住所１〜７の上指定値から下指定値まで順に連結し返します。
	 * @param kamiIndex 上指定値
	 * @param shimoIndex 下指定値
	 * @return 連結された住所
	 */
	public String getAdNaka(int kamiIndex,  int shimoIndex)
	{
		return getAdNakaIndex(kamiIndex,  shimoIndex,  false,  false);
	}

	/**
	 * 住所１から下から順に指定した値まで連結し返します。
	 * @param shimoIndex 指定値
	 * @return 連結された住所（半角スペースあり）
	 */
	public String getAdShimoHankakuSpace(int shimoIndex)
	{
		return getAdShimoIndex(shimoIndex,  true,  false);
	}

	/**
	 * 住所１から下から順に指定した値まで連結し返します。
	 * @param shimoIndex 指定値
	 * @return 連結された住所（全角スペースあり）
	 */
	public String getAdShimoZenkakuSpace(int shimoIndex)
	{
		return getAdShimoIndex(shimoIndex,  false,  true);
	}

	/**
	 * 住所１から下から順に指定した値まで連結し返します。
	 * @param shimoIndex 指定値
	 * @return 連結された住所
	 */
	public String getAdShimo(int shimoIndex)
	{
		return getAdShimoIndex(shimoIndex,  false,  false);
	}
	
	/**
	 * 入力されたインデックスが1〜7の間かをチェックします。
	 * @param index インデックス
	 * @return 判定結果
	 */
	private boolean checkIndex(int index)
	{
		return 0 < index && index < 8;
	}
	
	/**
	 * 住所１〜７までを指定されたインデックスまで連結して返します。
	 * @param kamiIndex 指定上インデックス
	 * @param addHankakuSpace 半角スペース要否
	 * @param addZenkakuSpace 全角スペース要否
	 * @return 連結値
	 */
	private String getAdKamiIndex(int kamiIndex,  boolean addHankakuSpace,  boolean addZenkakuSpace)
	{
		return getAdNakaIndex(1,  kamiIndex,  addHankakuSpace,  addZenkakuSpace);
	}

	/**
	 * 	/**
	 * 住所１〜７までを指定されたインデックスまで連結して返します。
	 * @param staIndex 連結開始位置
	 * @param endIndex 連結終了位置
	 * @param addHankakuSpace 半角スペース付与有無
	 * @param addZenkakuSpace 全角スペース付与有無
	 * @return 連結値
	 */
	private String getAdNakaIndex(int staIndex,  int endIndex,  boolean addHankakuSpace,  boolean addZenkakuSpace)
	{
		if(!checkIndex(staIndex) || !checkIndex(endIndex) || staIndex > endIndex)
		{
			return null;
		}

		StringBuilder sb = new StringBuilder();
		String[] adArr = getAdAll();
		for(int i = staIndex - 1; i < endIndex; i++)
		{
			if(i != endIndex + 1)
			{
				if(!isNull(adArr[i]))
				{
					sb.append(adArr[i]);
					if(i != endIndex - 1)
					{
						if(addHankakuSpace)
						{
							sb.append(HANKAKU_SPACE);
						}
						else if(addZenkakuSpace)
						{
							sb.append(ZENKAKU_SPACE);
						}
					}
				}
			}
		}
		if(addHankakuSpace)
		{
			while(sb.indexOf(HANKAKU_SPACE) == 0)
			{
				sb.deleteCharAt(0);
			}
			while(sb.lastIndexOf(HANKAKU_SPACE) == sb.length() - 1 && sb.lastIndexOf(HANKAKU_SPACE) != -1)
			{
				sb.deleteCharAt(sb.length() - 1);
			}
		}
		if(addZenkakuSpace)
		{
			while(sb.indexOf(ZENKAKU_SPACE) == 0)
			{
				sb.deleteCharAt(0);
			}
			while(sb.lastIndexOf(ZENKAKU_SPACE) == sb.length() - 1 && sb.lastIndexOf(ZENKAKU_SPACE) != -1)
			{
				sb.deleteCharAt(sb.length() - 1);
			}
		}
		return sb.toString();
	}
	
	/**
	 * 住所１〜７までを指定されたインデックスまで連結して返します。
	 * @param shimoIndex 指定下インデックス
	 * @param addHankakuSpace 半角スペース要否
	 * @param addZenkakuSpace 全角スペース要否
	 * @return 連結値
	 */
	private String getAdShimoIndex(int shimoIndex,  boolean addHankakuSpace,  boolean addZenkakuSpace)
	{
		return getAdNakaIndex(7 - shimoIndex + 1,  7,  addHankakuSpace,  addZenkakuSpace);
	}
}
