package org.itscool.commons.document;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * JavaBeansオブジェクトをＸＭＬドキュメントに展開するためのクラスです
 * @version 1.00A 2006/08/23 新規作成
 * @author kano
 *
 */
public class BeanToXmlDocument extends XmlDocument{
    
    /**
     * ルート名「rootName」で指定した新しいDocumentインスタンスを
     * 作成します
     * @param rootName このドキュメントのルート要素の名前
     * @throws Exception
     */
    public BeanToXmlDocument(String rootName) throws Exception{
        super(rootName);
    }
    
    /**
     * 指定されたDocumentインスタンスを使います
     * @param document 既存のDocumentインスタンス
     * @throws Exception
     */
    public BeanToXmlDocument(Document document) throws Exception{
        super(document);
    }
    
    /**
     * 指定されたオブジェクトをドキュメントに追加します
     * @param bean ドキュメントに追加するオブジェクト
     * @param elementName オブジェクトの要素名（NULLを指定した場合は
     * クラス名がセットされます）
     * @throws Exception
     */
    public void addElement(Object bean, String elementName) throws Exception{
        DocumentBean pBean = DocumentBeanParser.parseBean(bean);
        if( elementName != null ){
            pBean.setName(elementName);
        }
        addElement(pBean);
    }
    
    /**
     * 指定されたオブジェクトをドキュメントに追加します<BR>
     * 要素名はオブジェクトのクラス名がセットされます
     * @param bean ドキュメントに追加するオブジェクト
     * @throws Exception
     */
    public void addElement(Object bean) throws Exception{
        DocumentBean pBean = DocumentBeanParser.parseBean(bean);
        addElement(pBean);
    }
    
    /**
     * Object配列に登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param objects ドキュメントに追加するObject配列
     * @param elementName オブジェクトの要素名
     * @throws Exception
     */
    public void addElement(Object[] objects, String elementName) throws Exception{
        for( int i=0; i<objects.length; i++){
            Object bean = objects[i];
            DocumentBean pBean = DocumentBeanParser.parseBean(bean);
            if( elementName != null ){
                pBean.setName(elementName);
            }
            addElement(pBean);
        }
    }
    
    /**
     * Object配列に登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param objects ドキュメントに追加するObject配列
     * @throws Exception
     */
    public void addElement(Object[] objects) throws Exception{
        for( int i=0; i<objects.length; i++){
            Object bean = objects[i];
            DocumentBean pBean = DocumentBeanParser.parseBean(bean);
            addElement(pBean);
        }
    }
    
    /**
     * Listインスタンスに登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param list ドキュメントに追加するListインスタンス
     * @param elementName オブジェクトの要素名
     * @throws Exception
     */
    public void addElement(List list, String elementName) throws Exception{
        for( int i=0; i<list.size(); i++){
            Object bean = list.get(i);
            DocumentBean pBean = DocumentBeanParser.parseBean(bean);
            if( elementName != null ){
                pBean.setName(elementName);
            }
            addElement(pBean);
        }
    }
    
    /**
     * Listインスタンスに登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param list ドキュメントに追加するListインスタンス
     * @throws Exception
     */
    public void addElement(List list) throws Exception{
        for( int i=0; i<list.size(); i++){
            Object bean = list.get(i);
            DocumentBean pBean = DocumentBeanParser.parseBean(bean);
            addElement(pBean);
        }
    }
    
    /**
     * Mapインスタンスに登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param map ドキュメントに追加するMapインスタンス
     * @param elementName オブジェクトの要素名
     * @throws Exception
     */
    public void addElement(Map map, String elementName) throws Exception{
        Set set = map.keySet();
        Iterator it = set.iterator();
        while( it.hasNext()){
            Object key = it.next();
            Object bean = map.get(key);
            DocumentBean pBean = DocumentBeanParser.parseBean(bean);
            if( elementName != null ){
                pBean.setName(elementName);
            }
            addElement(pBean);
        }
    }
    
    /**
     * Mapインスタンスに登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param map ドキュメントに追加するMapインスタンス
     * @throws Exception
     */
    public void addElement(Map map) throws Exception{
        Set set = map.keySet();
        Iterator it = set.iterator();
        while( it.hasNext()){
            Object key = it.next();
            Object bean = map.get(key);
            DocumentBean pBean = DocumentBeanParser.parseBean(bean);
            addElement(pBean);
        }
    }
    
    /**
     * JavaBeans展開オブジェクトをドキュメントに追加します
     * @param pBean ドキュメントに追加するParseBeanインスタンス
     * @throws Exception
     */
    protected void addElement(DocumentBean pBean) throws Exception{
        Element root = document.getDocumentElement();
        Element beanElement = document.createElement(pBean.getName());
        Set set = pBean.keySet();
        Iterator it = set.iterator();
        while(it.hasNext()){
            String name = (String)it.next();
            Object object = pBean.getValue(name);
            if(object instanceof DocumentBean){
                Element element = document.createElement(name);
                addChild((DocumentBean)object, element);
                beanElement.appendChild(element);
            }else{
                String value = (String)pBean.getValue(name);
                Element element = document.createElement(name);
                element.appendChild(document.createTextNode(value));
                beanElement.appendChild(element);
            }
        }
        root.appendChild(beanElement);
    }
    
    /**
     * Elementインスタンスに子DocumentBeanインスタンスを追加します
     * @param pBean 子DocumentBeanインスタンス
     * @param element 親のElementインスタンス
     * @throws Exception
     */
    protected void addChild(DocumentBean pBean, Element element) throws Exception{
        Set set = pBean.keySet();
        Iterator it = set.iterator();
        while(it.hasNext()){
            String name = (String)it.next();
            Object object = pBean.getValue(name);
            if(object instanceof DocumentBean){
                Element magoChild = document.createElement(name);
                addChild((DocumentBean)object, magoChild);
                element.appendChild(magoChild);
            }else{
                String value = (String)pBean.getValue(name);
                Element child = document.createElement(name);
                child.appendChild(document.createTextNode(value));
                element.appendChild(child);
            }
        }
        
    }
}



