package org.itscool.commons.document;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * POJOをDocumentBeanクラスに変換するためのクラスです<BR>
 * POJO以外のインスタンスの変換は動作保障外です
 * @author kanou
 *
 */
public class DocumentBeanParser {
    /**
     * 指定されたオブジェクトをParseBeanインスタンスに変換します
     * @param bean ParaseBeanに変換するオブジェクト
     * @return 変換結果
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public static DocumentBean parseBean(Object bean, Class clazz, AbstractDocument document)
    throws IllegalAccessException, InvocationTargetException{
        DocumentBean pBean = new DocumentBean();
        
        Object property;
        
        String clazzTagName  = document.isReplaceClassToTagName(clazz.getName());
        if( clazzTagName == null ){
            clazzTagName = clazz.getName();
            int index = clazzTagName.lastIndexOf(".");
            clazzTagName = clazzTagName.substring(index+1, clazzTagName.length());
        }
        pBean.setName(clazzTagName);
//		System.out.println(clazzName);
        
        Method[] methods = clazz.getMethods();
        for(int i=0; i<methods.length; i++){
            Method method = methods[i];
            String getterName = method.getName();
            if( ( getterName.indexOf("get") == 0 || getterName.indexOf("is") == 0 )
            && getterName.indexOf("getClass") != 0 ){
                
                //メソッドの戻り値が配列の場合
                Class propertyType =  method.getReturnType();
                if( propertyType.isArray() ){
                    Object[] collection = (Object[])method.invoke(bean, null);
                    Iterator iterator = Arrays.asList(collection).iterator();
                    property = iterator;
                }else{
                    // メソッドを実行
                    property = method.invoke(bean, null);
                }
//	            System.out.print(mName+"=");
//	            System.out.println(property.toString());
                int firstMemberIndex = 3;
                if(getterName.indexOf("is") == 0){
                    firstMemberIndex = 2;
                }
                String memberName = getterName.substring(firstMemberIndex, getterName.length());
                memberName = memberName.substring(0, 1).toLowerCase() +
                    memberName.substring(1, memberName.length());
                String tagName = document.isReplaceMemberToTagName(clazz.getName(), memberName);
                if(property instanceof Collection || property instanceof Iterator){
                    Iterator iterator;
                    if(property instanceof Collection ){
                        iterator = ((Collection)property).iterator();
                    }else{
                        iterator = (Iterator)property;
                    }
                    DocumentBean newBean = new DocumentBean();
                    if( tagName != null ){
                        newBean.setName(tagName);
                    }else{
                        newBean.setName(memberName);
                    }
                                        
                    while(iterator.hasNext()){
                        Object object = iterator.next();
                        if( object == null )continue;
                        DocumentBean childBean = parseBean(object, object.getClass(), document);
                        newBean.add(childBean);
                    }
                    pBean.add(newBean);
                }else if(property instanceof Map){
                    Map map = (Map)property;
                    DocumentBean newBean = new DocumentBean();
                    if( tagName != null ){
                        newBean.setName(tagName);
                    }else{
                        newBean.setName(memberName);
                    }
                    Set keySet = map.keySet();
                    Iterator iterator = keySet.iterator();
                    while(iterator.hasNext()){
                        Object key = iterator.next();
                        Object object = map.get(key);
                        if( object == null ) continue;
                        DocumentBean childBean = parseBean(object, object.getClass(), document);
                        newBean.add(childBean);
                    }
                    pBean.add(newBean);
                }else if( propertyType != null &&
                    !propertyType.isPrimitive() &&
                    !propertyType.getName().equals("java.util.Date") &&
                    !propertyType.getName().equals("java.lang.String") ){
                    //プロパティタイプがプリミティブ型のラッパーで無い場合
                    //pBean.put(memberName, parseBean(property));
                    if( property == null ) continue;
                    DocumentBean childBean = parseBean(property, propertyType, document);
                    if( tagName != null ){
                        childBean.setName(tagName);
                    }else{
                        childBean.setName(memberName);
                    }
                    pBean.add(childBean);
                }else{
                    //プロパティタイプがプリミティブ型のラッパーの場合
                    //pBean.put(memberName, property.toString());
                    DocumentBean newBean = new DocumentBean();
                    if( tagName != null ){
                        newBean.setName(tagName);
                    }else{
                        newBean.setName(memberName);
                    }
                    if( property == null ){
                        property = "";
                    }
                    newBean.setValue(property.toString());
                    pBean.add(newBean);
                }
            }
        }
        return pBean;
    }
}
