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

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;

import jp.co.cybec.cb3.exception.DataFormatException;
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;

/**
 * XMLファイルの項目を表すクラス。
 * @author Daisuke Suga
 */
public class XMLElement {

	/** ログ */
	private static final Log LOG = LogFactory.getLog(XMLElement.class);

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

	/**
	 * 項目の名前。
	 */
	private String name = null;

	/**
	 * 項目の値。
	 */
	private String value = null;

	/**
	 * 項目の名前空間のURI。
	 */
	private String uri = "";

	/**
	 * 項目のQName。
	 */
	private String qName = "";

	/**
	 * 項目の属性。
	 */
	private XMLAttributes attributes = new XMLAttributes();

	/**
	 * アクセッサのキー名。
	 */
	private String key = null;

	/**
	 * 検索パス。
	 */
	private String path = null;

	/**
	 * コンストラクタ。
	 *
	 * @param name 項目の名前
	 */
	public XMLElement(String name) {
		this(name, null, null);
	}

	/**
	 * コンストラクタ。<br>
	 * {@link XMLFileReader#selectPath(String)}で検索した結果を保持する場合に使用します。
	 *
	 * @param name 項目の名前
	 * @param key アクセッサのキー名
	 * @param path 検索パス
	 */
	protected XMLElement(String name, String key, String path) {
		this.name = name;
		this.key = key;
		this.path = path;
	}

	/**
	 * 項目の名前を取得します。
	 * @return 項目の名前
	 */
	public String getName() {
		return name;
	}

	/**
	 * 項目の値をStringで取得します。
	 * @return 項目の値
	 */
	public String getString() {
		return value;
	}

	/**
	 * 項目の値をStringで設定します。
	 * @param value 項目の値
	 */
	public void setString(String value) {
		this.value = value;
	}

	/**
	 * 項目の値をIntegerで取得します。
	 *
	 * @return 項目の値
	 * @throws DataFormatException データ型の変換に失敗したときに発生します。
	 */
	public Integer getInteger() throws DataFormatException {
		try {
			return value != null ? Integer.valueOf(value) : null;
		} catch (NumberFormatException e) {
			String messageId = key == null ? LogMessageConstant.CB3_ACCESSOR_FILEACCESS_005
					: LogMessageConstant.CB3_ACCESSOR_FILEACCESS_XML_003;
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_XML_007, messageId, name, value, key,
					path));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}
	}

	/**
	 * 項目の値をIntegerで設定します。
	 * @param value 項目の値
	 */
	public void setInteger(Integer value) {
		this.value = value != null ? value.toString() : null;
	}

	/**
	 * 項目の値をLongで取得します。
	 *
	 * @return 項目の値
	 * @throws DataFormatException データ型の変換に失敗したときに発生します。
	 */
	public Long getLong() throws DataFormatException {
		try {
			return value != null ? Long.valueOf(value) : null;
		} catch (NumberFormatException e) {
			String messageId = key == null ? LogMessageConstant.CB3_ACCESSOR_FILEACCESS_005
					: LogMessageConstant.CB3_ACCESSOR_FILEACCESS_XML_003;
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_XML_008, messageId, name, value, key,
					path));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}
	}

	/**
	 * 項目の値をLongで設定します。
	 * @param value 項目の値
	 */
	public void setLong(Long value) {
		this.value = value != null ? value.toString() : null;
	}

	/**
	 * 項目の値をFloatで取得します。
	 *
	 * @return 項目の値
	 * @throws DataFormatException データ型の変換に失敗したときに発生します。
	 */
	public Float getFloat() throws DataFormatException {
		try {
			return value != null ? Float.valueOf(value) : null;
		} catch (NumberFormatException e) {
			String messageId = key == null ? LogMessageConstant.CB3_ACCESSOR_FILEACCESS_005
					: LogMessageConstant.CB3_ACCESSOR_FILEACCESS_XML_003;
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_XML_009, messageId, name, value, key,
					path));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}
	}

	/**
	 * 項目の値をFloatで設定します。
	 * @param value 項目の値
	 */
	public void setFloat(Float value) {
		this.value = value != null ? value.toString() : null;
	}

	/**
	 * 項目の値をShortで取得します。
	 *
	 * @return 項目の値
	 * @throws DataFormatException データ型の変換に失敗したときに発生します。
	 */
	public Short getShort() throws DataFormatException {
		try {
			return value != null ? Short.valueOf(value) : null;
		} catch (NumberFormatException e) {
			String messageId = key == null ? LogMessageConstant.CB3_ACCESSOR_FILEACCESS_005
					: LogMessageConstant.CB3_ACCESSOR_FILEACCESS_XML_003;
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_XML_010, messageId, name, value, key,
					path));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}
	}

	/**
	 * 項目の値をShortで設定します。
	 * @param value 項目の値
	 */
	public void setShort(Short value) {
		this.value = value != null ? value.toString() : null;
	}

	/**
	 * 項目の値をBigDecimalで取得します。
	 *
	 * @return 項目の値
	 * @throws DataFormatException データ型の変換に失敗したときに発生します。
	 */
	public BigDecimal getBigDecimal() throws DataFormatException {
		try {
			return value != null ? new BigDecimal(value) : null;
		} catch (NumberFormatException e) {
			String messageId = key == null ? LogMessageConstant.CB3_ACCESSOR_FILEACCESS_005
					: LogMessageConstant.CB3_ACCESSOR_FILEACCESS_XML_003;
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_XML_011, messageId, name, value, key,
					path));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}
	}

	/**
	 * 項目の値をBigDecimalで設定します。
	 * @param value 項目の値
	 */
	public void setBigDecimal(BigDecimal value) {
		this.value = value != null ? value.toString() : null;
	}

	/**
	 * 項目の値をDateで取得します。
	 *
	 * @return 項目の値
	 * @throws DataFormatException データ型の変換に失敗したときに発生します。
	 */
	public Date getDate() throws DataFormatException {
		try {
			return value != null ? DateFormat.getDateInstance().parse(value) : null;
		} catch (ParseException e) {
			String messageId = key == null ? LogMessageConstant.CB3_ACCESSOR_FILEACCESS_005
					: LogMessageConstant.CB3_ACCESSOR_FILEACCESS_XML_003;
			DataFormatException ex = new DataFormatException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_XML_012, messageId, name, value, key,
					path));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}
	}

	/**
	 * 項目の値をDateで設定します。
	 * @param value 項目の値
	 */
	public void setDate(Date value) {
		this.value = value != null ? DateFormat.getDateInstance().format(value) : null;
	}

	/**
	 * 項目の名前空間のURIを取得します。
	 *
	 * @return 項目の名前空間のURI
	 */
	public String getURI() {
		return uri;
	}

	/**
	 * 項目の名前空間のURIを設定します。
	 *
	 * @param uri 項目の名前空間のURI
	 */
	public void setURI(String uri) {
		this.uri = uri;
	}

	/**
	 * 項目のQNameを取得します。
	 *
	 * @return 項目のQName
	 */
	public String getQName() {
		return qName;
	}

	/**
	 * 項目のQNameを設定します。
	 *
	 * @param qName 項目のQName
	 */
	public void setQName(String qName) {
		this.qName = qName;
	}

	/**
	 * 項目の属性を取得します。
	 * @return 項目が持つ全ての属性
	 */
	public XMLAttributes getAttributes() {
		return attributes;
	}

	/**
	 * 項目の属性を設定します。
	 * @param attributes 項目が持つ全ての属性
	 */
	public void setAttributes(XMLAttributes attributes) {
		this.attributes = attributes;
	}

	/**
	 * 項目の属性を追加します。
	 * @param attribute 属性
	 */
	public void putAttribute(XMLAttribute attribute) {
		attributes.putAttribute(attribute);
	}

	/**
	 * 項目の値をStringで取得します。
	 * @return 項目の値
	 */
	public String toString() {
		return value;
	}
}
