
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;

import java.lang.reflect.*;

// RTTI: Run Time Type Identification und Reflection
// Man kann nun verschiedene Klassen auswählen 
// hier wird ein Object mitttels ClassFor erzeugt

public class rtti04 extends JFrame {
     JTextArea _edit;

  private static final String PREFERRED_LOOK_AND_FEEL = "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel";

  private static void installLnF() {
    try {
      String lnfClassname = PREFERRED_LOOK_AND_FEEL;
      if (lnfClassname == null)
        lnfClassname = UIManager.getCrossPlatformLookAndFeelClassName();
      UIManager.setLookAndFeel(lnfClassname);
    } catch (Exception e) {
      System.err.println("Cannot install " + PREFERRED_LOOK_AND_FEEL
          + " on this platform:" + e.getMessage());
    }
  }


  //Frame konstruieren
  public rtti04() {
    setSize(800, 600);
    setTitle("Beispiel RTTI 4");
    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    // this.setResizable(false);
    setGUI();
  }

  void setGUI() {
     JButton BnAction1;
     JButton BnAction2;
     JButton BnAction3;

    this.getContentPane().setLayout ( new BorderLayout() );

    _edit = new JTextArea("");
    _edit.setFont( new Font("Arial", Font.BOLD,24));

    JScrollPane scrollpane = new JScrollPane(_edit);
    this.getContentPane().add(scrollpane, BorderLayout.CENTER);

    JPanel panel = new JPanel();
    panel.setLayout( new FlowLayout() );
    BnAction1 = new JButton( "RTTI Person" );
    BnAction1.setFont( new Font("Arial", Font.BOLD,32));

    BnAction2 = new JButton( "RTTI Student" );
    BnAction2.setFont( new Font("Arial", Font.BOLD,32));

    BnAction3 = new JButton( "Class For" );
    BnAction3.setFont( new Font("Arial", Font.BOLD,32));

    panel.add(BnAction1);
    panel.add(BnAction2);
    panel.add(BnAction3);
    this.getContentPane().add(panel, BorderLayout.SOUTH);


    BnAction1.addActionListener(new java.awt.event.ActionListener() {
       public void actionPerformed(ActionEvent e) {
        BnAction1_Click();
       }
    });
    BnAction2.addActionListener(new java.awt.event.ActionListener() {
       public void actionPerformed(ActionEvent e) {
        BnAction2_Click();
       }
    });
    BnAction3.addActionListener(new java.awt.event.ActionListener() {
       public void actionPerformed(ActionEvent e) {
        BnAction3_Click();
       }
    });

  } // setGUI

  private String printClass(Class c, String s, boolean bAll) {
     int i;
     Method[] m;
     Constructor[] ctor;
     String name;
     // class c = Class.forName( sDbDrv );
     s += "Classname: "+c.getName();
     s += "\n" + "Ist ein Interface: "+c.isInterface();
     s += "\n\n";

     ctor = c.getConstructors();
     s += "Konstruktoren:" ;
     for (i=0; i<ctor.length; i++) {
       s += "\n" + ctor[i].toString();
     }
     s += "\n\n" ;
     s += "Methoden:" ;
     m = c.getMethods();
     for (i=0; i<m.length; i++) {
       name = m[i].toString();
       int j1 = name.indexOf(46);
       int j2 = name.lastIndexOf(46);

       if (j1==j2)
         s += "\n" + m[i].toString();
       else {
         if (bAll) {
           s += "\n" + m[i].toString();
         }
       }
     }
     s += "\n\n" ;

     return s;
  }

  private void Check_Class(String classname) {
     Class c = null;
     Class cy = null;
     String s="";
     //JLabel lab = new JLabel("text");
     try {
       c = Class.forName(classname);
       s = printClass(c,s,false);

       cy = c.getSuperclass();
       Object obj;
       try {
        obj = cy.newInstance();
        s = printClass(obj.getClass() ,s, true);
        _edit.setText(s);
       }
       catch ( InstantiationException e) {
         System.out.println("Error1 InstantiationException" +e);
       }
       catch ( IllegalAccessException e) {
         System.out.println("Error2 IllegalAccessException" +e);
       }

     }
     catch ( ClassNotFoundException e) {
         System.out.println("Error3 ClassNotFoundException" +e);
     }

  } // Check_Class(String classname) {

  private void BnAction1_Click() {
     Check_Class("Person");
  } // RTTI

  private void BnAction2_Click() {
     Check_Class("Student");
  } // RTTI


  private void Create_Class(String sClassname) {
     Class c = null;
     Object obj;
     String s="Name der Klasse: "+sClassname+"\n";
     Method[] m;  // Array der Methoden
     Field[] fields;  // // Array der Attribute

     try {
         // Erzeugen der Klasse
       c = Class.forName( sClassname );
       try {
        obj = c.newInstance(); // Erzeugen einer Instanz der Klasse
        s+="  Obj(toString):  " + obj +"\n"; // Verwendet toString()

        s+="  Methoden suchen\n"; 
        m = c.getMethods(); // Liefert die Methoden
        for (int i=0; i<m.length; i++) {
           String s1 = m[i].toString(); // aktuelle Methodenname
           if ( s1.indexOf("setName")>=0 ) {
                  // Methode der Oberklasse nun aufrufen
                Object args[] = { new String("Meier") }; // Parameter
                // Methode ausführen am Objekt obj
                m[i].invoke(obj, args );
           }
           if ( s1.indexOf(sClassname+".")>=0 ) {
             s+=s1+"\n";
             if ( s1.indexOf("setMatrNr")>=0 ) {
                Object args[] = { new Integer(22) }; // Parameter MatrNr
                s+="  setzt die Matrikelnummer auf 22\n"; 
                // Methode ausführen am Objekt obj
                m[i].invoke(obj, args );
             }
             if ( s1.indexOf("getMatrNr")>=0 ) {
                Object args[] = { }; // Keine Parameter
                // Methode ausführen am Objekt obj
                // hier aber der Inhalt beim Initialisieren
                Integer matrnr = (Integer) m[i].invoke(obj, args );
                s+="   Methode getMatrnr(): "+matrnr +"\n";
             }

           } // if
        } // for

        s+="\n\n";
        s+="  Attribute suchen\n"; 
         // Bestimmen der Attribute der Klasse
        s+="  Obj(toString):  " + obj ; // Verwendet toString()

         s+="\n\nAttribute: \n";
         fields = c.getDeclaredFields();
         for (int i=0; i<fields.length; i++) {
           Field field = fields[i];
              s+="  "+field.toString() +"\n";
              s+="    "+field.getName() +"\n";
              s+="    "+field.getType() +"\n";
              if ( field.getName().compareTo("MatrNr")==0) {
                field.setInt(obj, 123);
              }
              if ( field.getName().compareTo("Note")==0) {
                field.setDouble(obj, 3.3);
              }
         }

        s+="\n\n";
        // s+="  Obj(toString):  " + obj ; // Verwendet toString()
        // Ausgabe des Textes
         _edit.setText(s);
       }
       catch ( InstantiationException e) {
         System.out.println("Error1");
       }
       catch ( IllegalAccessException e) {
         System.out.println("Error2");
       }
       catch ( InvocationTargetException e) {
         System.out.println("Error3");
       }

     }
     catch ( ClassNotFoundException e) {
       System.out.println("Error4");
     }

  }  // Class For


  private void BnAction3_Click() {
     //Create_Class("Person");
     Create_Class("Student");
  }  // Class For


  public static void main(String[] args) {
    installLnF();
    rtti04 frame = new rtti04();
//    frame.setUndecorated(true);
//    frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
    frame.setVisible(true);
  }


}



class Person {
   protected String Name;

  public Person() {
    Name="";
  }

   public Person(String Name) {
     this.Name = Name;
   }
   public String getName() {
     return Name;
   }
  public void print() {
     System.out.println(  Name );
  }

  public String toString() {
    return "Name: "+Name;
  }


}


class Student extends Person {

  int MatrNr;
  double Note;


  public Student() {
    super("");
    MatrNr = 11;
    Note=1.3;
  }

  public Student(String Name, int MatrNr) {
    super(Name);
    this.MatrNr = MatrNr;
  }

  public void print() {
     super.print();
     System.out.println(  "MatrNr: "+MatrNr );
  }


   public int getMatrNr() {
     return MatrNr;
   }
   public void setMatrNr(int MatrNr) {
     this.MatrNr = MatrNr;
   }

  public String toString() {
    return super.toString()  + "  MatrNr: "+MatrNr+"   Note: "+Note;
  }

}



