import java.lang.reflect.* ;
import java.beans.Beans ;
import java.util.HashMap;

@SuppressWarnings("rawtypes")
public class Reflection {
  private HashMap<String, Class> recognizedTypes ;
  private HashMap<Method, String> detectedSetMethods ;
  
  public Reflection() {
	  this.recognizedTypes=new HashMap<String, Class>() ;
	  this.recognizedTypes.put("boolean",Boolean.TYPE) ;
	  this.recognizedTypes.put("int",Integer.TYPE) ;
	  this.recognizedTypes.put("double",Double.TYPE) ;
	  this.recognizedTypes.put("java.lang.String",String.class) ;
  }
  
  
  public boolean isRecognizedType (String typeName) {
	  return this.recognizedTypes.get(typeName) !=null ;
  }
  public Class [] getParamForSetter(String typeName) {
	  return  new Class[] { this.recognizedTypes.get(typeName)  };
  }
  
  public static void main(String args[]) {
	
	Reflection analyseComponent = new Reflection() ;
	analyseComponent.run(args[0]) ;
	
  }
    
  public void run(String className) {
	String setName, propertyName ;
	this.detectedSetMethods = new HashMap<Method,String>();  
    System.out.println("--- Partie Introspection de "+className+" ---") ;
    try {
	Object obj = Beans.instantiate(null,className) ;
	Class<?> laClasse = obj.getClass() ;
	for (Method m :  laClasse.getMethods()) {
	  String typeName=m.getReturnType().getName() ;	
	  if ((m.getName().startsWith("get") || 
		   (m.getName().startsWith("is") &&  typeName.equals("boolean"))) &&
	      m.getParameterTypes().length==0 && isRecognizedType(typeName)) { 
		  int ind ;
		  if (typeName.equals("boolean")) ind=2 ; else ind=3 ;
		  setName="set"+m.getName().substring(ind) ;
		  propertyName = m.getName().substring(ind,ind+1).toLowerCase() 
				         +m.getName().substring(ind+1) ;
          try {           
	        Method methodeSet=laClasse.getMethod(setName,getParamForSetter(typeName)) ;    
	        detectedSetMethods.put(methodeSet,typeName) ;
		    System.out.println(typeName+" property found : "+propertyName) ;
          } catch(NoSuchMethodException e1) { 
          	// No corresponding setter method found (setName) 
          }
	    }
	}
	System.out.println("--- Partie Invocation dynamique ---") ;
	for (Method m : detectedSetMethods.keySet()) {
      String typeName=detectedSetMethods.get(m) ;		
	  System.out.println("invoke method "+m.getName()+" with "+typeName+" parameter") ;
	  if (typeName.equals("boolean")) m.invoke(obj,true) ;
	  else if (typeName.equals("int") ) m.invoke(obj,0) ;
	  else if (typeName.equals("double") ) m.invoke(obj,0.0) ;
	  else if (typeName.equals("String") ) m.invoke(obj,"Hello World !") ;
	}
    } catch (ArrayIndexOutOfBoundsException e) {
	System.err.println("Erreur : java Reflection class name") ;
    } catch (SecurityException e) {
	System.err.println("exception raised...") ;
    } catch(IllegalAccessException e) {
	System.err.println("Access...") ;
    } catch(InvocationTargetException e) {
	System.err.println("Argument...") ;
    } catch(IllegalArgumentException e) {
	System.err.println("Argument...") ;
    } catch(java.io.IOException e) {
	System.err.println("IO...") ;
    } catch(ClassNotFoundException e) {
	System.err.println("class...") ;
    }
  }  
}
