/*
 * RecordFieldReaderFormat.java
 * Copyright (C) 2008 Cyber Beans Corporation. All rights reserved.
 */
package jp.co.cybec.cb3.accessor.fileaccess;

import java.math.BigDecimal;
import java.util.Date;

import jp.co.cybec.cb3.exception.DataFormatException;
import jp.co.cybec.cb3.util.DateUtil;
import jp.co.cybec.cb3.util.NumberUtil;
import jp.co.cybec.cb3.util.logging.ErrorCodeConstant;
import jp.co.cybec.cb3.util.logging.LogMessageConstant;
import jp.co.cybec.cb3.util.logging.LogMessageFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * ファイルのレコード項目をフォーマットするクラス(Reader用)。
 * @author  Jianming Guo
 */
public class RecordFieldReaderFormat implements RecordFieldReaderFormatable {
	/** ログ */
	private static final Log LOG = LogFactory.getLog(RecordFieldReaderFormat.class);

	/** メッセージ */
	private static final LogMessageFactory MESSAGE = new LogMessageFactory(
			LogMessageConstant.CB3_MESSAGE_FILENAME);

	/** 設定ファイルパス */
	private String filepath = null;

	/** 項目名 */
	private String field = null;

	/**
	 * コンストラクタ
	 *
	 * @param filepath 設定ファイルパス
	 * @param field 項目名
	 */
	public RecordFieldReaderFormat(String filepath, String field){
		this.filepath = filepath;
		this.field = field;
	}

	/**
	 * 引数の文字列をフォーマットします。
	 *
	 * @param pattern フォーマット
	 * @param type タイプ
	 * @param data フォーマット対象の文字列
	 * @return フォーマット後の文字列
	 * @throws DataFormatException データ型の変換に失敗したときに発生します。
	 */
	public String format(String pattern, String type, String data) throws DataFormatException {
		String retValue = null;

		// 引数の文字列がNULL or 空白の場合
		if (data == null || data.trim().length() == 0) {
			return data;
		}

		// パターンが未指定の場合
		if (pattern == null || pattern.length() == 0) {
			return data;
		}

		// タイプが未指定 or タイプが正しくない場合
		if (type == null || (!type.equalsIgnoreCase(RecordFieldConstants.TYPE_NUMBER)
				&& !type.equalsIgnoreCase(RecordFieldConstants.TYPE_DATE))) {
			DataFormatException ex = new DataFormatException(MESSAGE
					.getErrorMessage(ErrorCodeConstant.ACCESSOR_FILEACCESS_001,
							LogMessageConstant.CB3_ACCESSOR_FILEACCESS_008, this.filepath,
							this.field, type));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}

		try {
			if (type.equalsIgnoreCase(RecordFieldConstants.TYPE_NUMBER)) {
			// タイプ：数字の場合
				// 文字列→BigDecimalに変換
				BigDecimal bNum = NumberUtil.parseBigDecimal(pattern, data);

				// BigDecimal→数字の文字列に変換
				retValue = NumberUtil.numberToString(bNum, NumberUtil.getFractionDigits(pattern));

			} else {
			// タイプ：日付の場合
				// 文字列→Dateに変換
				Date date = DateUtil.parseDate(data, pattern);
				// Date→デフォルトフォーマットの文字列に変換
				retValue = DateUtil.formatDate(date);
			}
		} catch (Exception e) {
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_002,
					LogMessageConstant.CB3_ACCESSOR_FILEACCESS_007, this.field, data, pattern));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}

		return retValue;
	}

	/**
	 * 引数の文字列をトリムします。
	 * (パディング文字を取り除きます)
	 *
	 * @param algin   アラインメント指定子(右寄せ・左寄せ)
	 * @param padding パディング文字
	 * @param data トリム対象の文字列
	 * @return パディング文字を取り除いた文字列
	 * @throws DataFormatException アラインメント指定子、パディング文字の指定に間違いがある場合に発生します。
	 */
	public String trim(String algin, String padding, String data) throws DataFormatException {
		String retValue = null;

		if(data == null){
			return null;
		}

		// どちらか未設定の場合
		if ((algin == null || algin.trim().length() == 0) ||
				(padding == null || padding.length() == 0)) {
			return data;
		}

		// アラインメントのチェック
		if (!algin.equalsIgnoreCase(RecordFieldConstants.ALGIN_LEFT)
				&& !algin.equalsIgnoreCase(RecordFieldConstants.ALGIN_RIGHT)) {
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_003,
					LogMessageConstant.CB3_ACCESSOR_FILEACCESS_011, this.filepath, this.field,
					algin));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}

		// パディング文字のバイト数チェック
		if (padding.getBytes().length > 1) {
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_004,
					LogMessageConstant.CB3_ACCESSOR_FILEACCESS_012, this.filepath, this.field,
					padding));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}

		char paddingChar = padding.charAt(0);
		if (algin.equalsIgnoreCase(RecordFieldConstants.ALGIN_LEFT)) {
		// 左寄せの場合
			int index = data.length();
			for (int i = data.length() -1 ; i >= 0; i--) {
				if (data.charAt(i) != paddingChar) {
					break;
				}
				index = i;
			}
			retValue = data.substring(0, index);
		} else {
		// 右寄せの場合
			int index = -1;
			for (int i = 0 ; i <= data.length() - 1; i++) {
				if (data.charAt(i) != paddingChar) {
					break;
				}
				index = i;
			}
			retValue = data.substring(index + 1);
		}

		return retValue;
	}
}
