/*
 * Created on Jul 27, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package jreport.uds.javabean;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Vector;

import jreport.uds.javabean.beans.SimpleBeanTest;

/**
 * @author jennyw
 *
 * This Java class is used to populate the default data for each property in the Java Bean recursively. 
 * It uses DataTypeMapping to deside if the Class is able to populate with data, and also it gets the
 * default value for the object from the DataTypeMapping table.
 */
public class FakeDataGeneratorForJavaBean {
	public static void populate( Object data, 
			Hashtable collectionPropInfo, 
			int numOfRecords) throws IllegalArgumentException, 
				InvocationTargetException, InstantiationException, 
				IllegalAccessException, IntrospectionException, ClassNotFoundException{
		BeanInfo propBeanInfo = Introspector.getBeanInfo(data.getClass());
//		Vector 	columnInfo = new Vector();
		PropertyDescriptor[] propDescriptor = propBeanInfo.getPropertyDescriptors();
		UDSForJavaBeanLogger.debug("Populating data for Object:"+data);
		for( int i =0; i<propDescriptor.length; i++ ){
			
			
			Class clsPropType = propDescriptor[i].getPropertyType();
			if( clsPropType.equals(Class.class))
			    continue;
			
			if(!DataTypeMapping.isDetailCollectionClass(clsPropType)){
				SQLTypeInfo info = DataTypeMapping.getSQLType(clsPropType);
				UDSForJavaBeanLogger.debug("Class:"+clsPropType+" SQLType:"+(info==null?"Unknown":info.getTypeName()));
				
				if(info != null){
					Method writeMethod = propDescriptor[i].getWriteMethod();
					if(writeMethod != null){
						Object array[] = new Object[1];
						array[0]=info.getDefaultValue();
						
						writeMethod.invoke(data, array );
					}
				}else{
					Object obj = clsPropType.newInstance();
					Method writeMethod = propDescriptor[i].getWriteMethod();
					if( writeMethod != null){
						Object array[] = new Object[1];
						array[0]=obj;
						writeMethod.invoke(data, array );
						
						populate( obj, null, -1);
					}
				}
			}else if(DataTypeMapping.isQualifiedDetailCollection(clsPropType)){
				if( collectionPropInfo != null){
					
					String name = propDescriptor[i].getName();
					String clsName = (String)collectionPropInfo.get(name);
					if(clsName !=null){
						populateCollection( data, propDescriptor[i], clsName, numOfRecords,collectionPropInfo);
					}
				}
			}
		}
	}
	
	public static void  populateCollection(Object data, 
			PropertyDescriptor propDesc, 
			String elementClsName, 
			int num,
			Hashtable propInfo) throws IllegalArgumentException, 
							InvocationTargetException, 
							InstantiationException, 
							IllegalAccessException, IntrospectionException,ClassNotFoundException{
		
		Class clsProp = propDesc.getPropertyType();
		Class clsElement = Class.forName(elementClsName);
		Object collectionObj = null;
		
		if( clsProp.isArray()){
			collectionObj = Array.newInstance(clsElement, num);
			for(int i =0; i < num; i++){
				Object comp = clsElement.newInstance();
				populate(comp, propInfo,num);
				Array.set(collectionObj, i, comp);
			}
		}else if(clsProp.isAssignableFrom(Collection.class)){
			collectionObj = new ArrayList();
			for(int i =0; i < num; i++){
				Object comp = clsElement.newInstance();
				populate(comp, propInfo, num);
				((Collection)collectionObj).add(comp);
			}
		}else if(clsProp.isAssignableFrom(Vector.class)){
			collectionObj = (Vector)clsProp.newInstance();
			for(int i =0; i < num; i++){
				Object comp = clsElement.newInstance();
				populate(comp, propInfo,num);
				((Vector)collectionObj).addElement(comp);
			}
		}
		
		Method writeMethod = propDesc.getWriteMethod();
		if(writeMethod != null){
			Object arguments[] = new Object[1];
			arguments[0]=collectionObj;
			writeMethod.invoke(data, arguments);
		}
		
	}
	
	public static void main(String arg[]){
		Hashtable propInfo = new Hashtable();
		propInfo.put("persons", "jreport.uds.javabean.beans.Person");
		propInfo.put("addresses","jreport.uds.javabean.beans.Address");
		propInfo.put("historyrecords","jreport.uds.javabean.beans.PersonalHistoryRecord");
		
		for( int i =0; i< 2; i++){
			SimpleBeanTest test = new SimpleBeanTest();
			try {
				FakeDataGeneratorForJavaBean.populate(test,propInfo, 2);
//				System.out.println("Finished one...");
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IntrospectionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.exit(0);
		
	}
	
}
