
// implements ist das Schluesselwort fuer
// die Implementierung vorgegebener Java Interfaces
class Ttt implements MyComparable {
    int t1;
    int t2;

    public Ttt(int x, int y) {
	t1 = x;
        t2 = y;
    }

    public int myCompareTo(Object obj) {


        //BOOLscher Vergleichsoperator fuer 
        // die Abfrage, ob ein Objekt einer bestimmten Klasse
        // angehoert.
        if ( obj instanceof Ttt ) {

	    Ttt other = (Ttt)obj;
            int sqThis = t1*t1 + t2*t2;
            int sqOther = other.t1*other.t1 + other.t2*other.t2;
            
            return ( sqThis - sqOther );
            
	}
        else return -1;
       
    }

    // Uberladen der toString()-Methode
    public String toString() {
 
	return "("
               +(new Integer(t1)).toString() 
               + ","
               + (new Integer(t2)).toString()+ ")";

    }

}

public class MyMain {

    public static void main(String[] args) {

        MyFiniteStack stk1;

        stk1 = new MyFiniteStack();

        stk1.push(new Ttt(1,1));
        stk1.push(new Ttt(-1,1));
        stk1.push(new Ttt(2,1));

        // statische Variable class enthält codierte
        // Klassenidentifikation
        if ( stk1.getClass() == MyFiniteStack.class ) {
	    System.out.println("stk1 is of type MyFiniteStack");
	}



        // Mit stk1.getClass().getMethods() erhalten wir
        // einen Array mit Referenzen auf Objekte vom Typ Method
        // Jedes dieser Method-Objekte repräsentiert eine  Methode
        // des zu untersuchenden Objektes (hier stk1). Die Operationen
        // auf Method-Objekten können Auskunftsfunktionen über die
        // Methoden des zu untersuchenden Objektes aufgerufen werden:
        // stk1.getClass().getMethods()[iCnt].toString() liefert
        // die vollständige Deklaration der iCnt'ten Methode
        // von stk1 zurück. stk1.getClass().getMethods()[iCnt].getName()
        // liefert nur den Methodennamen.
	for (int iCnt=0; 
	     iCnt < stk1.getClass().getMethods().length; iCnt++)
	    System.out.println(
            "Name stk1, method number "  
			       + iCnt 
			       + " is: " 
			 + stk1.getClass().getMethods()[iCnt].toString());


        // Mit der invoke()-Methode auf dem Method-Objekt 
        // stk1.getClass().getMethods()[iCnt] kann man die iCnt'te
        // Methode des Objektes stk1 aufrufen:
        // Statische Klassenmethoden werden mit invoke(null,parms)
        // aufgerufen, objektabhängige Methoden mit
        // invoke(objectReference,parms). Parms ist ein Array mit
        // Referenzen auf die Parameterobjekte, die beim Methodenaufruf
        // zu verwenden sind. Der Array ist in der Reihenfolge der
        //  Parameterliste zu belegen. (Wie denn sonst wohl ...)
        // Ist der Methodenaufruf parameterlos, wird invoke(...,null)
        // verwendet.

        // invoke() mit statischer Methode, keine Parameter:
        try {
	    System.out.println("Name of  method  " 
	    + stk1.getClass().getMethods()[0].getName()
			       + " returns "
			       + stk1.getNumExistingStacks()
			       + " which is the same as "
	    + stk1.getClass().getMethods()[0].invoke(null,null));
	}
        catch (java.lang.IllegalAccessException e){
	    System.out.println(e);
	}
        catch (java.lang.reflect.InvocationTargetException e){
	    System.out.println(e);
	}

        
        Ttt obj, objPrev = null;

        for (int iCnt=0; 
              iCnt < stk1.peek().getClass().getMethods().length; iCnt++)
          System.out.println("Name of Top-of-stack object, method number "  
                             + iCnt 
                             + " is: " 
                             + stk1.peek().getClass().getMethods()[iCnt]);


        // ivoke() mit objekt-abhängiger Methode. Die Methode wird
        // auf dem Objekt stk1.peek() (hier vom Typ Ttt) angewendet.
        try {
        System.out.println("Name of Top-of-stack Class =  " 
			   + stk1.peek().getClass().getName()
                           + " has value "
                           + stk1.peek().toString()
                           + " which is the same as "
                           + stk1.peek().getClass().getMethods()[3].
                               invoke(stk1.peek(),null));
	}
        catch (java.lang.IllegalAccessException e){
	    System.out.println(e);
	}
        catch (java.lang.reflect.InvocationTargetException e){
	    System.out.println(e);
	}

        // invoke() auf stk-Methode (Nummer 10 ist push()) mit einem
        // Parameter anwenden:
        Object oa[] = new Object[1];
        oa[0] = new String("String-auf-den-Stack");

        try {
	    stk1.getClass().getMethods()[10].invoke(stk1,oa);
	}
        catch (java.lang.IllegalAccessException e){
	    System.out.println(e);
	}
        catch (java.lang.reflect.InvocationTargetException e){
	    System.out.println(e);
	}

        System.out.println("Mit invoke() auf den Stack gelegt: "
                           + stk1.pop());

    }

}

