/*
 * $Id: NodeFactory.java,v 1.1 2005/11/03 09:41:48 sugimotokenichi Exp $
 * Copyright (C) 2005 SUGIMOTO Ken-ichi
 * 作成日: 2005/07/24
 */
package feat.v1.template;

import feat.v1.impl.template.HTMLNodeFactoryImpl;


/**
 * HTMLのツリーを操作するためのユーティリティ。
 * @author SUGIMOTO Ken-ichi
 */
public class NodeFactory {

    /**
     * ドキュメントノード(HTMLツリーのルートのノード)を作る。
     * @return
     */
    public static HTMLDocument createHTMLDocument() {
        return HTMLNodeFactoryImpl.createHTMLDocument();
    }

    /**
     * どのツリーにも属さない要素ノードを作る。
     * @param tagName タグの名前
     * @param endTag 終了タグが必要ならtrue
     * @return
     */
    public static HTMLElement createHTMLElement(String tagName, boolean endTag) {
        return HTMLNodeFactoryImpl.createHTMLElement(tagName, endTag);
    }

    /**
     * どのツリーにも属さないテキストノードを作る。
     * @param text テキストノードに格納する文字列。この文字列はエスケープされる。nullを渡してもよい
     * @return
     */
    public static HTMLText createHTMLText(String text) {
        return HTMLNodeFactoryImpl.createHTMLText(text);
    }

    /**
     * どのツリーにも属さない注釈ノードを作る。
     * @param text 注釈ノードに格納する文字列。nullを渡してもよい
     * @return
     * @throws RemarkTextException
     */
    public static HTMLRemark createHTMLRemark(String text) throws RemarkTextException {
        return HTMLNodeFactoryImpl.createHTMLRemark(text);
    }

    //
    // ノードの基本操作
    //

    /*
     * nodeの後ろにnewNodeを挿入する。
     * nodeまたはnewNodeがnullのときは何もしない。
     * @param node 追加する基準のノード
     * @param newNode 新しく追加するノード。連鎖リストになっていても良い。
     * @return 追加したノード
     */
    /*public static HTMLNode insertAfter(HTMLNode node, HTMLNode newNode) {
        if ( node == null || newNode == null )
            return null;

        ControllableNode cNode = (ControllableNode)(node);
        ControllableNode next = (ControllableNode)(cNode.getNext());
        ControllableNode cNewNode = (ControllableNode)(newNode);
        ControllableNode last = (ControllableNode)(NodeSelectUtil.getLastNode(newNode));

        cNode.setNext(cNewNode);
        cNewNode.setPrev(cNode);
        last.setNext(next);
        if ( next != null ) {
            next.setPrev(last);
        }

        setParentAll(newNode, last, cNode.getParent());
        return newNode;
    }*/

    /*
     * startからendまでのノードの親ノードをnewParentに設定する。
     * @param start リストの最初のノード。nullのときは何もしない。
     * @param end リストの最後のノード。nullを指定するとstart以降のすべてのノードが対象になる
     * @param newParent
     */
    /*private static void setParentAll(HTMLNode start, HTMLNode end, HTMLNode newParent) {
        for(HTMLNode n = start; n != null; n = n.getNext()) {
            ((ControllableNode)n).setParent(newParent);
            if ( n == end ) {
                break;
            }
        }
    }*/
/*
    private static ControllableNode castControllableNode(HTMLNode node) throws UncontrollableNodeException {
        if ( node == null )
            return null;

        if ( node instanceof ControllableNode ) {
            return (ControllableNode)node;
        }
        else {
            throw new UncontrollableNodeException();
        }
    }
*/
    /*
     * nodeの前にnewNodeを挿入する。
     * nodeまたはnewNodeがnullのときは何もしない。
     * @param node 追加する基準のノード
     * @param newNode 新しく追加するノード。連鎖リストになっていても良い。
     * @return 追加したノード
     */
    /*public static HTMLNode insertBefore(HTMLNode node, HTMLNode newNode) {
        if ( node == null || newNode == null )
            return null;

        ControllableNode cNode = (ControllableNode)(node);
        ControllableNode prev = (ControllableNode)(node.getNext());
        ControllableNode parent = (ControllableNode)(node.getParent());
        ControllableNode cNewNode = (ControllableNode)(newNode);
        ControllableNode last = (ControllableNode)(NodeSelectUtil.getLastNode(newNode));

        if ( prev != null ) {
            prev.setNext(newNode);
        }
        cNewNode.setPrev(prev);
        last.setNext(node);
        cNode.setPrev(last);

        setParentAll(newNode, last, parent);

        if ( parent != null && parent.getFirstChild() == node ) {
            parent.setFirstChild(newNode);
        }
        return newNode;
    }*/

    /*
     * parentノードの子ノードにchildノードを追加する。
     * @param parent nullのときは何もしない
     * @param child nullのときは何もしない。単体でも連鎖リストになっていても良い。
     * @return 追加したノード
     */
    /*public static HTMLNode addChild(HTMLNode parent, HTMLNode child) {
        if ( parent == null || child == null )
            return null;

        ControllableNode cParent = (ControllableNode)(parent);
        ControllableNode cChild = (ControllableNode)(child);
        HTMLNode n = cParent.getFirstChild();
        if ( n == null ) {
            cParent.setFirstChild(child);
            cChild.setPrev(null);
            // すべてのノードの親を更新する
            setParentAll(child, null, parent);
        }
        else {
            addTail(n, child);
        }
        return child;
    }*/

    /*
     * startと同じ階層の最後にnodeを追加する。
     * @param start リストの先頭ノード。nullのときは何もしない。
     * @param node 追加するノード。nullのときは何もしない。連鎖リストになっていても良い。
     * @return 追加したノード
     */
    /*public static HTMLNode addTail(HTMLNode start, HTMLNode node) {
        if ( start == null || node == null )
            return null;

        ControllableNode cNode = (ControllableNode)(node);
        ControllableNode tail = (ControllableNode)NodeSelectUtil.getLastNode(start);
        tail.setNext(node);
        cNode.setPrev(tail);
        setParentAll(node, null, node.getParent());
        return node;
    }*/

    /*
     * nodeをツリーから切り離す。
     * @param node nullのときは何もしない
     * @return 切り離したノード
     */
    /*public static HTMLNode detach(HTMLNode node) {
        if ( node == null )
            return null;

        ControllableNode cNode = (ControllableNode)(node);
        ControllableNode parent = (ControllableNode)(node.getParent());
        ControllableNode prev = (ControllableNode)(node.getPrev());
        ControllableNode next = (ControllableNode)(node.getNext());

        // 親子の参照を切る
        if ( parent != null ) {
            // 削除するノードが最初の子ノードだったら
            // 次の兄弟ノードが最初の子ノードに繰り上がる
            if ( parent.getFirstChild() == node ) {
                parent.setFirstChild(next);
            }
        }
        cNode.setParent(null);

        // 兄弟の参照を切る
        if ( prev != null ) {
            prev.setNext(next);
        }
        if ( next != null ) {
            next.setPrev(prev);
        }
        cNode.setPrev(null);
        cNode.setNext(null);

        return node;
    }*/

    //
    // 基本操作を使った応用
    //

    /*
     * iteratorから得られるすべてのノードをツリーから切り離す。
     * このメソッドはiteratorからノードを削除するのではなく、各ノードが所属するツリーからノードを切り離す。
     * iteratorが返すHTMLNode以外のオブジェクトは無視する。
     * @param iterator HTMLNodeを返す反復子
     */
    /*public static void detach(Iterator iterator) {
        while(iterator.hasNext()) {
            Object x = iterator.next();
            if ( x instanceof HTMLNode ) {
                detach((HTMLNode)x);
            }
        }

    }*/


}
