package org.phosphoresce.commons.html;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * HTMLエレメント上位抽象クラス<br>
 *
 * @author Kitagawa<br>
 *
 *<!--
 * 更新日		更新者			更新内容
 * 2008/11/19	Kitagawa		新規作成
 *-->
 */
public abstract class HTMLElement {

	/** 親エレメント */
	private HTMLElement parent;

	/** 子エレメント */
	private List childs;

	/**
	 * コンストラクタ<br>
	 */
	public HTMLElement() {
		super();
		this.parent = null;
		this.childs = new LinkedList();
	}

	/**
	 * 親エレメントを取得します。<br>
	 * @return 親エレメント
	 */
	public HTMLElement getParent() {
		return parent;
	}

	/**
	 * 親エレメントを設定します。<br>
	 * 元の親エレメントから自身のエレメントを削除し、新たな親エレメントに子供として追加されます。<br>
	 * 尚、ここでnullを指定した場合、自身が親となる、独立したエレメントとなります。<br>
	 * @param parent 親エレメント
	 */
	public void setParent(HTMLElement parent) {
		if (this.parent != null) {
			this.parent.removeChild(this);
		}
		this.parent = parent;
		if (parent != null) {
			parent.addChild(this);
		}
	}

	/**
	 * エレメントがルートエレメント(親を持たない)であるか判定します。<br>
	 * @return ルートエレメントである場合にtrueを返却
	 */
	public boolean isRoot() {
		return parent == null;
	}

	/**
	 * 自身をルートエレメントとします。<br>
	 * これはsetParent(null)とした場合と同様の動作を行います。<br>
	 */
	public void setRoot() {
		setParent(null);
	}

	/**
	 * エレメントが子エレメントの操作をサポートしているか判定します。<br>
	 * おそらくコメントやテキストエレメントはこれをfalseとして返却します。<br>
	 * @return 子エレメントの操作をサポートしている場合にtrueを返却
	 */
	public abstract boolean isSupportChild();

	/**
	 * 子エレメントを追加します。<br>
	 * @param element エレメントオブジェクト
	 * @throws NullPointerException エレメントにnullオブジェクトを指定した場合に発生します
	 * @throws UnsupportedOperationException エレメントクラスにおいてこのメソッドがサポートされていない場合に発生します
	 */
	public void addChild(HTMLElement element) {
		if (!isSupportChild()) {
			throw new UnsupportedOperationException("addChild unsupported");
		}
		if (element == null) {
			throw new NullPointerException("element is null");
		}
		element.parent = this;
		childs.add(element);
	}

	/**
	 * 子エレメントを削除します。<br>
	 * @param element エレメントオブジェクト
	 * @throws NullPointerException エレメントにnullオブジェクトを指定した場合に発生します
	 * @throws UnsupportedOperationException エレメントクラスにおいてこのメソッドがサポートされていない場合に発生します
	 */
	public void removeChild(HTMLElement element) {
		if (!isSupportChild()) {
			throw new UnsupportedOperationException("removeChild unsupported");
		}
		if (element == null) {
			throw new NullPointerException("element is null");
		}
		if (!childs.contains(element)) {
			return;
		}
		element.parent = null;
		childs.remove(element);
	}

	/**
	 * 指定されたインデックスの子エレメントを取得します。<br>
	 * @param index インデックス
	 * @return エレメントオブジェクト
	 */
	public HTMLElement getChild(int index) {
		return (HTMLElement) childs.get(index);
	}

	/**
	 * 子エレメントリストを取得します。<br>
	 * @return 子エレメントリスト
	 */
	protected List getChilds() {
		return childs;
	}

	/**
	 * 子エレメントの数を取得します。<br>
	 * @return 子エレメントの数
	 */
	public int getChildCount() {
		return childs.size();
	}

	/**
	 * 子エレメント反復子を取得します。<br>
	 * @return 子エレメント反復子
	 */
	public Iterator getChildIterator() {
		return childs.iterator();
	}

	/**
	 * オブジェクトの文字列表現を返します。<br>
	 * @return オブジェクトの文字列表現
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("{");
		buffer.append("parent=");
		buffer.append(parent);
		buffer.append(",");
		buffer.append("childs=");
		buffer.append(childs);
		buffer.append("}");
		return buffer.toString();
	}
}

