package org.itscool.commons.document;

import java.util.HashMap;
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{
        Class clazz = bean.getClass();
        DocumentBean pBean = DocumentBeanParser.parseBean(bean, clazz, this);
        if( elementName != null ){
            pBean.setName(elementName);
        }
        addElement(pBean);
    }
    
    /**
     * 指定されたオブジェクトをドキュメントに追加します<BR>
     * 要素名はオブジェクトのクラス名がセットされます
     * @param bean ドキュメントに追加するオブジェクト
     * @throws Exception
     */
    public void addElement(Object bean) throws Exception{
        Class clazz = bean.getClass();
        DocumentBean pBean = DocumentBeanParser.parseBean(bean, clazz, this);
        addElement(pBean);
    }
    
    /**
     * Object配列に登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param objects ドキュメントに追加するObject配列
     * @param elementName オブジェクトの要素名
     * @throws Exception
     */
    public void addElement(Object[] objects, String elementName) throws Exception{
        DocumentBean pParentBean = new DocumentBean();
        pParentBean.setName(elementName);
        for( int i=0; i<objects.length; i++){
            Object bean = objects[i];
            if( bean == null ) continue;
            Class clazz = bean.getClass();
            DocumentBean pBean = DocumentBeanParser.parseBean(bean, clazz, this);
            pParentBean.add(pBean);
        }
        addElement(pParentBean);
    }
    
    /**
     * Object配列に登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param objects ドキュメントに追加するObject配列
     * @throws Exception
     */
    public void addElement(Object[] objects) throws Exception{
        addElement(objects, "array");
    }
    
    /**
     * Listインスタンスに登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param list ドキュメントに追加するListインスタンス
     * @param elementName オブジェクトの要素名
     * @throws Exception
     */
    public void addElement(List list, String elementName) throws Exception{
        DocumentBean pParentBean = new DocumentBean();
        pParentBean.setName(elementName);
        for( int i=0; i<list.size(); i++){
            Object bean = list.get(i);
            if( bean == null ) continue;
            Class clazz = bean.getClass();
            DocumentBean pBean = DocumentBeanParser.parseBean(bean, clazz, this);
            pParentBean.add(pBean);
        }
        addElement(pParentBean);
    }
    
    /**
     * Listインスタンスに登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param list ドキュメントに追加するListインスタンス
     * @throws Exception
     */
    public void addElement(List list) throws Exception{
        addElement(list, "list");
    }
    
    /**
     * Mapインスタンスに登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param map ドキュメントに追加するMapインスタンス
     * @param elementName オブジェクトの要素名
     * @throws Exception
     */
    public void addElement(Map map, String elementName) throws Exception{
        DocumentBean pParentBean = new DocumentBean();
        pParentBean.setName(elementName);
        Set set = map.keySet();
        Iterator it = set.iterator();
        while( it.hasNext()){
            Object key = it.next();
            Object bean = map.get(key);
            if( bean == null ) continue;
            Class clazz = bean.getClass();
            DocumentBean pBean = DocumentBeanParser.parseBean(bean, clazz, this);
            pParentBean.add(pBean);
        }
        addElement(pParentBean);
    }
    
    /**
     * Mapインスタンスに登録されているオブジェクトをドキュメントに
     * 追加します<BR>
     * @param map ドキュメントに追加するMapインスタンス
     * @throws Exception
     */
    public void addElement(Map map) throws Exception{
        addElement(map, "map");
    }
    
    /**
     * JavaBeans展開オブジェクトをドキュメントに追加します
     * @param pBean ドキュメントに追加するParseBeanインスタンス
     * @throws Exception
     */
    protected void addElement(DocumentBean pBean) throws Exception{
        Element root = document.getDocumentElement();
        Element beanElement = document.createElement(pBean.getName());
        int size = pBean.size();
        for(int i=0; i<size; i++){
            DocumentBean child = (DocumentBean)pBean.get(i);
            
            String name = child.getName();
            String value = (String)child.getValue();
            
            Element element = document.createElement(name);
            if( value != null){
                element.appendChild(document.createTextNode(value));
            }
            addChild(child, element);
            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()){
        int size = pBean.size();
        for(int i=0; i<size; i++){
            DocumentBean child = (DocumentBean)pBean.get(i);
            String name = child.getName();
            String value = (String)child.getValue();
//            if(object instanceof DocumentBean){
                Element childElement = document.createElement(name);
                if( value != null ){
                    childElement.appendChild(document.createTextNode(value));
                }
                if(child.size() > 0){
                    addChild(child, childElement);
                }
                element.appendChild(childElement);
//            }else{
//                String value = object.toString();
//                Element childElement = document.createElement(name);
//                childElement.appendChild(document.createTextNode(value));
//                element.appendChild(childElement);
//            }
        }
        
    }
}



