// ino.module.Class.8553.package 
package mycompiler.myclass;
// ino.end
// ino.module.Class.8553.import 
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

import mycompiler.AClassOrInterface;
import mycompiler.mybytecode.ClassFile;
import mycompiler.myexception.CTypeReconstructionException;
import mycompiler.myexception.JVMCodeException;
import mycompiler.myexception.SCClassBodyException;
import mycompiler.myexception.SCClassException;
import mycompiler.myexception.SCExcept;
import mycompiler.mymodifier.Modifiers;
import mycompiler.mystatement.*;
import mycompiler.mytype.GenericTypeVar;
import mycompiler.mytype.Pair;
import mycompiler.mytype.RefType;
import mycompiler.mytype.SuperWildcardType;
import mycompiler.mytype.Type;
import mycompiler.mytype.TypePlaceholder;
import mycompiler.mytype.WildcardType;
import mycompiler.mytypereconstruction.CReconstructionTuple;
import mycompiler.mytypereconstruction.CSubstitution;
import mycompiler.mytypereconstruction.CSupportData;
import mycompiler.mytypereconstruction.CTriple;
import mycompiler.mytypereconstruction.TypeinferenceResultSet;
import mycompiler.mytypereconstruction.replacementlistener.CReplaceTypeEvent;
import mycompiler.mytypereconstruction.set.CReconstructionTupleSet;
import mycompiler.mytypereconstruction.set.CSubstitutionSet;
import mycompiler.mytypereconstruction.set.CTripleSet;
import mycompiler.mytypereconstruction.set.CTypeAssumptionSet;
import mycompiler.mytypereconstruction.set.IHashSetKey;
import mycompiler.mytypereconstruction.typeassumption.CInstVarTypeAssumption;
import mycompiler.mytypereconstruction.typeassumption.CLocalVarTypeAssumption;
import mycompiler.mytypereconstruction.typeassumption.CMethodTypeAssumption;
import mycompiler.mytypereconstruction.typeassumption.CParaTypeAssumption;
import mycompiler.mytypereconstruction.typeassumption.CTypeAssumption;
import mycompiler.mytypereconstruction.typeassumptionkey.CMethodKey;
import mycompiler.mytypereconstruction.unify.Unify;
import mycompiler.SourceFile;

import org.apache.log4j.Logger;
// ino.end


import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import typinferenz.ConstraintsSet;
import typinferenz.JavaCodeResult;
import typinferenz.OderConstraint;
import typinferenz.ResultSet;
import typinferenz.TypinferenzException;
import typinferenz.UndConstraint;
import typinferenz.FunN;
import typinferenz.assumptions.TypeAssumptions;



// ino.class.Class.23010.declaration 
public class Class extends AClassOrInterface
// ino.end
// ino.class.Class.23010.body
{
    // ino.attribute.superclassid.23014.decldescription type=line
    // private Status      status;
    // ino.end
    // ino.attribute.superclassid.23014.declaration 
    public UsedId      superclassid = (SourceFile.READ_OBJECT_SUPERCLASSES_FROM_JRE?UsedId.createFromQualifiedName("Object",-1):null);
    // ino.end
    // ino.attribute.body.23017.declaration 
    private ClassBody   body;
    // ino.end
    // ino.attribute.class_block.23020.decldescription type=line
    // private Class       java;
    // ino.end
    // ino.attribute.class_block.23020.declaration 
    private Block       class_block;
    // ino.end
    // ino.attribute.paralist.23023.declaration 
    private Vector<Type>      paralist = new Vector<Type>();    // Parameterliste 'class xy<para1, para2,...>{}' wird gespeichert
    // ino.end
    // ino.attribute.parahash.23026.declaration 
    private Hashtable<String,String>   parahash = new Hashtable<String,String>();  // parametrisierten Attrib. werden mit den Paramet.aus paralist verk.
    // ino.end
    // ino.attribute.isFirstLocalVarDecl.23029.declaration 
    public static boolean isFirstLocalVarDecl; //Hilfsvariable fuer Offsets, hoth
    // ino.end

    private Vector<GenericTypeVar> genericClassParameters=new Vector<GenericTypeVar>();
    
    // ino.attribute.containedTypes.23032.decldescription type=line
    // PL 05-07-30 eingefuegt. Vektor aller Typdeklarationen, die in der Klasse        
    // vorkommen. Wird in der Studienarbeit von Andreas Stadelmeier nur f�r Verifizierung der Tests eingesetzt.
    // ino.end
    // ino.attribute.containedTypes.23032.declaration 
    private Vector<Type> containedTypes = new Vector<Type>();
    // ino.end
    // ino.attribute.usedIdsToCheck.23035.declaration 
    private Vector<UsedId> usedIdsToCheck = new Vector<UsedId>();
    // ino.end

    private TypeAssumptions typeAssumptions = null;//muss mit null Initialisiert werden. Darf nur �ber getTypeAssumptions abgerufen werden.
    private Vector<Method> methodList = null; // gleich wie typeAssumptions
    
    // ino.attribute.parserlog.23038.declaration 
    protected Logger parselog  = Logger.getLogger("parser");
    // ino.end
	protected Logger typinferenzLog = Logger.getLogger("Typeinference");

    
    // ino.method.Class.23041.definition 
    public Class(String name)
    // ino.end
    // ino.method.Class.23041.body 
    {
        super(name);
        if(name.equals("java.lang.Object")){
            superclassid=null;
        }
    }
    // ino.end
    
    // ino.method.Class.23044.definition 
    public Class(String name, Modifiers mod)
    // ino.end
    // ino.method.Class.23044.body 
    {
        super(name, mod);
        if(name.equals("java.lang.Object")){
            superclassid=null;
        }       
    }
    // ino.end
    
    // ino.method.Class.23047.defdescription type=javadoc
    /**
     * Konstruktor, der die Angabe aller Parameter ermoeglicht. 
     * Zur Uebersichtlichkeit in der Grammatik. 
     */
    // ino.end
    // ino.method.Class.23047.definition 
    public Class(String name, Modifiers mod, ClassBody cb, Vector<Type> ct, Vector<UsedId> usedIdsToCheck,
            UsedId superclass, Vector<UsedId> superif, Vector<Type> paralist)
    // ino.end
// ino.method.Class.23047.body 
{
        super(name, mod);
        if (cb != null) set_ClassBody(cb);
        if (ct != null) setContainedTypes(ct);
        if (superclass != null) set_UsedId(superclass);
        if (superif != null) setSuperInterfaces(superif);
        if (paralist != null) this.set_ParaList(paralist);
        if(usedIdsToCheck!=null) this.usedIdsToCheck=usedIdsToCheck;

        // HOTI 10.5.06
        // Object darf natuerlich nicht Object als Superklasse haben
        // Sonst gibt es eine endlosaufloesung
        if(name.equals("java.lang.Object")){
            superclassid=null;
        }
        
        parserlog.debug("Neue Klasse: " + name);
        
    
    }
// ino.end
    
    // ino.method.getUsedIdsToCheck.23050.definition 
    public Vector<UsedId> getUsedIdsToCheck()
    // ino.end
    // ino.method.getUsedIdsToCheck.23050.body 
    {
        return usedIdsToCheck;
    }
    // ino.end
    // ino.method.setContainedTypes.23053.definition 
    public void setContainedTypes(Vector<Type> containedTypes)
    // ino.end
    // ino.method.setContainedTypes.23053.body 
    {
    this.containedTypes = containedTypes;
    }
    // ino.end

    // ino.method.getContainedTypes.23056.definition 
    public Vector<Type> getContainedTypes()
    // ino.end
    // ino.method.getContainedTypes.23056.body 
    {
    return containedTypes;
    }
    // ino.end

    // ino.method.para_check.23059.definition 
    public void para_check(Vector<Class> classlist, boolean ext)
    throws SCClassException
    // ino.end
    // ino.method.para_check.23059.body 
    {
    //pr�ft, ob jeder Key in der parahash-Tabelle auch im Vector paralist steht bzw. umgekehrt.
    
    parahash = body.init_parahashtable(paralist,ext);
    // Para_check erstellt Hashtabelle der Klasse this.get_classname + parahash.toString()+paralist.toString());
    
    for(Enumeration el = paralist.elements(); el.hasMoreElements();)
    {
        Type typ = (Type)el.nextElement();
        if(!parahash.contains(typ.getName()))
        {
            parserlog.error("");
            parserlog.error("Fehler: unbekannter Parameter: "+ typ.getName());
    
            SCExcept neu=new SCExcept();
            neu.set_error("Fehler: unbekannter Parameter: "+ typ.getName());
            neu.set_statement("Class");
            SCClassException except = new SCClassException();
            Vector<SCExcept> v = new Vector<SCExcept>();
            v.add(neu);
            except.addException(v);
            except.addClassname(getName());
            throw except;
        }
    }
    
    if(superclassid != null)
    {
        String superclassname;
        Vector superclass = superclassid.get_Name();
    
        // superclass darf nur ein Element haben, da es in Java keine Mehrfachvererbung gibt!
        for(Enumeration el = superclass.elements();el.hasMoreElements();)
        {
            superclassname = (String) el.nextElement();
            // Alle Klassen in der Klassenliste (enth�lt alle definierten Klassen) durchgehen
            for ( Enumeration<Class> e2 = classlist.elements(); e2.hasMoreElements(); )
            {
                Class basis =e2.nextElement();
                // Klasse im Vektor == Superklasse
                if( basis.getName().equals(superclassname) )
                {
                    if( basis.paralist != null && superclassid!=null && superclassid.get_ParaList()!=null)
                    {
                        // System/.out.println( "Basis: " + basis.get_ParaList() );
                        // if( basis.get_ParaList().size() > 0 ) System/.out.println( "0: " + ((TypePlaceholder)basis.get_ParaList().elementAt(0)).get_Type() );
                        // if( basis.get_ParaList().size() > 1 ) System/.out.println( "1: " + ((TypePlaceholder)basis.get_ParaList().elementAt(1)).get_Type() );
                        // otth: geaender auf vParaOrg                      
                        if(basis.paralist.size() != this.superclassid.get_ParaList().size())
                        {
                            SCExcept neu = new SCExcept();
                            neu.set_error("Parameterlisten von Basis und Child unterscheiden sich in der L�nge!");
                            neu.set_classname(getName());
                            neu.set_statement("Class");
                            SCClassException except = new SCClassException();
                            Vector<SCExcept> v = new Vector<SCExcept>();
                            v.add(neu);
                            except.addException(v);
                            except.addClassname(getName());
    //                          Exceptions werfen aufgrund vom eingestellten
    //                          Debug-Level???   
    //                          if( MyCompiler.DebugLevel != MyCompiler.UNIFICATION_INFO)
    //                              throw except;
                            parserlog.debug("Parameterlistenl�ngenpr�fung von Basis- u. Superkl. tempor�r ausgeschalten! - otth");
                        }
                    }
                }
            }
        }
    
        try
        {
        parahash = body.complete_parahashtable(classlist, superclassid,parahash, ext);
        }
        catch(SCClassBodyException ex){
        SCClassException except = new SCClassException();
        except.addException(ex.get_exlist());
        except.addClassname(getName());
        throw except;
        }
    
        paralist = complete_paralist(ext);     //Parameterliste wird um die Eintr�ge der Basisklasse erg�nzt
        // vParaOrg wird hier nicht veraendert
    }
    
    else
    {
        // typinferenzLog.debug("\tkeine Vererbung gefunden!");
    }
    
    /*
    if(ext)
    {
        string_rec("++ ParaCheck Globale Parameterliste: ",paralist);typinferenzLog.debug();
        string_rec("++ ParaCheck Globale ParaHashtabelle: ", parahash);typinferenzLog.debug();
    }
    */
       }
    // ino.end

    // ino.method.complete_paralist.23062.definition 
    public Vector<Type> complete_paralist(boolean ext)
    // ino.end
    // ino.method.complete_paralist.23062.body 
    {
    
    //Diese Funktion vervollt�ndigt die Parameterliste f�r vererbte Klassen
    Vector<Type> child = paralist;
    
    paralist = (Vector<Type>)superclassid.get_ParaList();
    
    for(Enumeration<Type> e = child.elements();e.hasMoreElements();){
        paralist.addElement(e.nextElement());
    }
    
    return this.paralist;
    }
    // ino.end

    // ino.method.sc_check_for_extended_classes.23068.definition 
    public void sc_check_for_extended_classes(Vector<Class> classlist, Hashtable<String,String> childhash,boolean ext)
    // ino.end
    // ino.method.sc_check_for_extended_classes.23068.body 
    {
    // Der Semantik-Check f�r Basis-Klassen - Aufgabe: In der mit �bergegeben Hashtable childhash sollen
    // die geerbten Funktionen und Methoden mit ihren zugeh�rigen Typen eingetragen werden
    
    String strSuperKlassenName = null;
    
    // otth: Hat diese Klasse wieder eine Supperklasse?
    if( superclassid != null)
    {
        Vector superclass = superclassid.get_Name();
        for(Enumeration el = superclass.elements();el.hasMoreElements();) //superclass darf nur ein Element haben!!!
        {
            strSuperKlassenName = (String) el.nextElement();
        }
    }
    
    // otth: Hashtabelle f�r Superklasse erestellen
    body.sc_init_hashtable_for_extended_classes(classlist, strSuperKlassenName, childhash, paralist, parahash, body.kill, ext);
    }
    // ino.end
    
    
    
    // ino.method.codegen.23071.definition 
    public void codegen(SourceFile sf)
    throws JVMCodeException
    // ino.end
    // ino.method.codegen.23071.body 
    {
        ClassFile classfile = new ClassFile();
        String superClass;
    
        // Handling der Superklasse
        if(superclassid != null) {
            superClass = superclassid.get_codegen_UsedId();
        } else {
            superClass = "java/lang/Object";
        }
        
        // Handling der Package
        String pkgName = "";
        if (sf.getPackageName() != null) {
            pkgName = sf.getPackageName().get_codegen_UsedId() + "/";
        }
        
        classfile.add_class(getName(), pkgName,  superClass, getAccessFlags());
        
        // Handling fuer Superinterfaces
        classfile.addSuperInterfaces(getSuperInterfaces());
        
        // Generics hinzufuegen - falls erforderlich
        classfile.addGenerics(this.paralist,superclassid, this.getSuperInterfaces());
        
        // Body der Classfile generieren
        if(body != null) {
            body.codegen(classfile, this.paralist);
        }
    
        // Ueberpruefung, ob Konstruktor generiert
        // Falls nicht, default-Konstruktor erzeugen
        if(!classfile.get_constructor_founded()) {
            classfile.add_method("<init>", "()V", null, null, null, (short)0, this.paralist, false);
        }
        
        classfile.codegen();
        
        codegenlog.info("Compilierung erfolgreich abgeschlossen, "+ getName() + ".class erstellt.");
    }
    // ino.end
    
    // ino.method.set_UsedId.23074.definition 
    public void set_UsedId (UsedId uid)
    // ino.end
    // ino.method.set_UsedId.23074.body 
    {
    this.superclassid = uid;
    }
    // ino.end

    // ino.method.set_ClassBody.23077.definition 
    public void set_ClassBody(ClassBody body)
    // ino.end
    // ino.method.set_ClassBody.23077.body 
    {
    this.body = body;
    }
    // ino.end

    // ino.method.set_class_block.23080.definition 
    public void set_class_block(Block block)
    // ino.end
    // ino.method.set_class_block.23080.body 
    {
    this.class_block = block;
    }
    // ino.end

    // ino.method.is_member.23083.definition 
    public String is_member(String var)
    // ino.end
    // ino.method.is_member.23083.body 
    {
        Hashtable h;
        h=body.get_hash();
        return (String)h.get(var);
    }
    // ino.end

    // ino.method.get_Superclass_Name.23086.definition 
    public String get_Superclass_Name()
    // ino.end
    // ino.method.get_Superclass_Name.23086.body 
    {
        if(superclassid!=null)
        return superclassid.getQualifiedName();
        else
        return null;
    }
    // ino.end

    // ino.method.get_ClassBody.23089.definition 
    public ClassBody get_ClassBody()
    // ino.end
    // ino.method.get_ClassBody.23089.body 
    {
        return body;
    }
    // ino.end

    // ino.method.get_class_block.23092.definition 
    public Block get_class_block()
    // ino.end
    // ino.method.get_class_block.23092.body 
    {
        return class_block;
    }
    // ino.end

    // ino.method.does_Class_extend.23095.definition 
    public boolean does_Class_extend()
    // ino.end
    // ino.method.does_Class_extend.23095.body 
    {
    if(superclassid==null)
        return false;
    else
        return true;
    }
    // ino.end

    // ino.method.set_ParaList.23098.definition 
    public void set_ParaList(Vector<Type> para)
    // ino.end
    // ino.method.set_ParaList.23098.body 
    {
        this.paralist = para;
    }
    // ino.end

    // ino.method.get_ParaList.23101.definition 
    public Vector get_ParaList()
    // ino.end
    // ino.method.get_ParaList.23101.body 
    {
        return this.paralist;
    }
    // ino.end

    // ino.method.set_ParaHash.23104.definition 
    public void set_ParaHash(Hashtable<String,String> hash)
    // ino.end
    // ino.method.set_ParaHash.23104.body 
    {
        this.parahash = hash;
    }
    // ino.end

    // ino.method.get_ParaHash.23107.definition 
    public Hashtable<String,String> get_ParaHash()
    // ino.end
    // ino.method.get_ParaHash.23107.body 
    {
        return this.parahash;
    }
    // ino.end



/*static void string_rec(Hashtable ht){
    String record="";
    boolean isError=false;
    record=record.concat("[");
    for(Enumeration e=ht.elements(),k=ht.keys();e.hasMoreElements();){
        String s = (String)k.nextElement();
        Object o = e.nextElement();

        record=record.concat(" "+s);

        if(o instanceof Type){
            record=record.concat(" = "+((Type)o).getName());
        } else if(o instanceof Hashtable){
            record=record.concat("= ");
            string_rec((Hashtable)o);
            if(e.hasMoreElements())
                record=record.concat(", ");
            } else if(o instanceof String){
                record=record.concat(" = "+o);
                if(e.hasMoreElements())
                    record=record.concat(", ");
                }
            else {
                record=("[FEHLER: string_rec: unbekannter Typ!!!!!!");
                isError=true;
            }
        }
        record=record.concat("]");
        if(isError){
            parserlog.error(record);
        }else{
            parserlog.debug(record);
        }
    }*/

    /*static void string_rec(Vector v){
        String record=("{");
        for(Enumeration e=v.elements();e.hasMoreElements();){
            Type t = (Type)e.nextElement();
            record=record.concat(" "+t.getName());
    
            if(e.hasMoreElements())
            record=record.concat(",");
        }
        record=record.concat("}");
        parserlog.debug(record);
    }*/
    /*static void string_rec(String st, Hashtable ht){
    String record=(st);
    boolean isError=false;
    record=record.concat("[");
    for(Enumeration e=ht.elements(),k=ht.keys();e.hasMoreElements();){
        String s = (String)k.nextElement();
        Object o = e.nextElement();

        record=record.concat(" "+s);

        if(o instanceof Type){
        record=record.concat(" = "+((Type)o).getName());
        }

        else if(o instanceof Hashtable){
        record=record.concat("= ");
        string_rec((Hashtable)o);
        if(e.hasMoreElements())
            record=record.concat(", ");
        }
        else if(o instanceof String){
        record=record.concat(" = "+o);
        if(e.hasMoreElements())
            record=record.concat(", ");
        }
        else {
            record=("[FEHLER: string_rec: unbekannter Typ!!!!!! " +o);
            isError = true;
        }
    }
    record=record.concat("]");
    if(isError){
        parserlog.error(record);
    }else{
        parserlog.debug(record);
    }
    }*/

    /*static void string_rec(String st,Vector v)
    {
        String record=(st);
        record=record.concat("{");
        for(Enumeration e=v.elements();e.hasMoreElements();)
        {
            Type t = (Type)e.nextElement();
            record=record.concat(" "+t.getName());
            if(e.hasMoreElements())
            {
                record=record.concat(", ");
            }
        }
        record=record.concat("}");
        parserlog.debug(record);
    }*/

    
    /////////////////////////////////////////////////////////////////////////
    // TypeReconstructionAlgorithmus
    /////////////////////////////////////////////////////////////////////////
    // ino.method.TRProg.23110.defdescription type=javadoc
    /**
     * Ausgangspunkt f�r den Typrekonstruktionsalgorithmus. Hier werden zun�chst
     * die Mengen von Typannahmen V_fields_methods und V_i erstellt, die als Eingabe
     * f�r den Algorithmus dienen.<br/>
     * (siehe Algorithmus 5.17 TRProg, Martin Pl�micke)
     * <br/>Author: J�rg B�uerle
     * @param supportData
     * @param globalAssumptions 
     * @return Liste aller bisher berechneten, m�glichen Typkombinationen
     * @throws CTypeReconstructionException
     */
    // ino.end
    // ino.method.TRProg.23110.definition 
    public Vector<TypeinferenceResultSet> TRProg(CSupportData supportData, TypeAssumptions globalAssumptions)
    throws CTypeReconstructionException
    // ino.end
    // ino.method.TRProg.23110.body 
    {
    	/*
        
        */
        //////////////////////////////
        // Und los geht's:
        //////////////////////////////
        inferencelog.info("Rufe TRStart()...");
        //////////////////////////////
        //  Ab hier ...
        //  @author A10023 - Andreas Stadelmeier:
        //////////////////////////////
        //Erzeuge Assumptions:
        TypeAssumptions assumptions = this.getTypeAssumptions();
        //--
        assumptions.add(globalAssumptions);
        
        //Generiere Liste mit Expressions, welche zur Initialisierung von Feldern verwendet werden.
        Vector<Expr> fieldInitializers = new Vector<Expr>();
        for(FieldInitialization field : body.getFieldInitializations()){
        	Assign fieldAssign = new Assign(0,0);
        	Expr expr1 = new LocalOrFieldVar(field.getName(), 0);
        	Expr expr2 = field.getWert();
        	fieldAssign.set_Expr(expr1, expr2);
        	fieldInitializers.add(fieldAssign);
        }
        
        ConstraintsSet oderConstraints = this.TYPE(this.getMethodList(), fieldInitializers, assumptions);
        typinferenzLog.debug("Erstellte Constraints: "+oderConstraints);

        //Die Constraints in Pair's umwandeln:
        Vector<Vector<Pair>> xConstraints = new Vector<Vector<Pair>>();// = oderConstraints.getConstraints();
        for(Vector<UndConstraint> uC:oderConstraints.getConstraints()){ //mit dem getConstraints-Aufruf wird das Karthesische Produkt erzeugt.
        	Vector<Pair> cons = new Vector<Pair>();
        	for(UndConstraint undCons:uC){
        		cons.addAll(undCons.getConstraintPairs());
        	}
        	xConstraints.add(cons);
        }
        typinferenzLog.debug("Karthesisches Produkt der Constraints: "+xConstraints);
        
        //////////////////////////////
        // Unifizierung der Constraints:
        //////////////////////////////
        Vector<TypeinferenceResultSet> ret = new Vector<TypeinferenceResultSet>(); //Generiere das Result-Set
        for(Vector<Pair> constraints : xConstraints){
        	//Alle durch das Karthesische Produkt entstandenen M�glichkeiten durchgehen:
            Vector<Vector<Pair>> result = new Vector<Vector<Pair>>();
            
            //Alle FunN-Typen werden per clone-methode in RefTypes verwandelt. (Die clone Methode in FunN darf nicht �berschrieben werden.
            for(Pair p : constraints){
            	if(p.TA1 instanceof FunN){
            		p.TA1 = p.TA1.clone();
            	}
            	if(p.TA2 instanceof FunN){
            		p.TA2 = p.TA2.clone();
            	}
            }
            
            //Erst die Unifizierung erstellen:
            Vector<Vector<Pair>> unifyResult = Unify.unify(constraints, supportData.getFiniteClosure());
        	//Dann den Ergebnissen anf�gen
            result.addAll(unifyResult);
        
	        // Debugoutput:Vector<Vector<Pair>>
	        typinferenzLog.debug("Unifiziertes Ergebnis: "+result);
	        
	        /*
	        // Pr�fe ob eindeutige L�sung:
	        if(result.size()>1 && !Unify.hasSolvedForm(result.elementAt(0))){
	        	
	        	typinferenzLog.debug("Keine eindeutige L�sung!");
	        	
	        }else if(result.size()>1){
	        	
	        	//Replace TPH:
	            for(Pair res : result.elementAt(0)){
	            	if(res.OperatorEqual()){
	            		if(res.TA1 instanceof TypePlaceholder)((TypePlaceholder)res.TA1).fireReplaceTypeEvent(new CReplaceTypeEvent(res.TA1, res.TA2));
	            	}
	            }
	        }
	        */
	        //typinferenzLog.debug();
	        //typinferenzLog.debug(supportData.getFiniteClosure());
	        typinferenzLog.debug("Typinformationen: \n"+this.getTypeInformation(this.getMethodList(), fieldInitializers));
	        
	        typinferenzLog.debug("\nJavaFiles:\n");
	        
	        //typinferenzLog.debug(this.printJavaCode(new ResultSet(new Vector<Pair>())));
	        
	
	        //Der Unifikationsalgorithmus kann wiederum auch mehrere L�sungen errechnen, diese werden im folgenden durchlaufen:
	        for(Vector<Pair> resultSet : result){
	        	//Add Result set as a new ReconstructionResult to ret:
	        	TypeinferenceResultSet reconstructionResult = new TypeinferenceResultSet(this);
	        	reconstructionResult.setConstraints(constraints);
	        	reconstructionResult.setUnifiedConstraints(resultSet);
	        	ret.add(reconstructionResult);
	        	
	        	//ResultSet res = new ResultSet(resultSet);
	        	typinferenzLog.debug("JavaFile f�r ResultSet "+reconstructionResult+"\n");
	        	typinferenzLog.debug(this.printJavaCode(reconstructionResult));
	        	
	        }
        
        }
        return ret;
        /*
        CReconstructionTupleSet retTupleSet = this.TRStart(methodList, V, V_fields_methods, supportData);
        inferencelog.debug("Bin aus TRStart() zur�ck in TRProg().");
        //////////////////////////////
        // Neu Ergebnismenge A aller
        // Typannahmen erzeugen:
        //////////////////////////////
        inferencelog.debug("Erstelle Ergebnismenge...");
        Vector<CTypeReconstructionResult> newA = new Vector<CTypeReconstructionResult>();
    
        // Alle bisherigen M�glichkeiten an Typkombinationen durchgehen:
        Vector<CTypeReconstructionResult> oldA = supportData.getA();
        for(int i=0; i<oldA.size(); i++){
            CTypeReconstructionResult oneReconResult = oldA.elementAt(i);
            
            // Und mit den neuen m�glichen Typkombinationen vereinigen:
            Iterator<CReconstructionTuple> retTupleIt = retTupleSet.getIterator();
            while(retTupleIt.hasNext()){
                CReconstructionTuple possibleTuple = retTupleIt.next();
                this.clear(possibleTuple.getAssumSet(), rememberLocals);
                
                // Neue Typinformationen mit alten Typinformationen vereinigen:
                CTypeReconstructionResult newReconResult = oneReconResult.shallowCopy();
                newReconResult.addDataFromTupel(possibleTuple);
        
    
        //PL 05-08-02 eingefuegt
        //Fuegt Klassen und GenericTypeVars zu A hinzu
                newReconResult.addClassName(this.getName());
        Vector<GenericTypeVar> genericsList = new Vector<GenericTypeVar>();
        for(int ii =0; ii<this.get_ParaList().size(); ii++){
            Type para = (Type)this.get_ParaList().elementAt(ii);
            if(para instanceof GenericTypeVar){
            genericsList.addElement((GenericTypeVar)para);
            }
        }
        newReconResult.addGenericTypeVars(this.getName(), genericsList);
    
        //Hinzuf�gen:
        newA.addElement(newReconResult);
            }
        }
        return newA;
        */
    }
	// ino.end

    /**
     * @return Eine Liste mit allen Methoden dieser Klasse
     */
    private Vector<Method> getMethodList() {
    	if(this.methodList  != null) return this.methodList;
    	//TODO: Unn�tige Berechnungen im folgenden Code rausk�rzen:
		//////////////////////////////
		// Die Eingabedaten bauen:
		//////////////////////////////
		inferencelog.debug("Baue Eingabedaten...");
		TypeAssumptions V_fields_methods = new TypeAssumptions(this.getName());
		Vector<Method> methodList = new Vector<Method>(); 
		Vector<CTypeAssumptionSet> V = new Vector<CTypeAssumptionSet>();
		Vector<CTypeAssumption> rememberLocals = new Vector<CTypeAssumption>();
		
		//////////////////////////////
		// Alle Felder durchgehen:
		// Zuerst alle Attribute, dann Methoden
		// ge�ndert: hoth 06.04.2006
		
		//////////////////////////////
		for(FieldDecl field : body.get_FieldDeclVector())
		{
		//////////////////////////////
		// Attribut:
		//////////////////////////////
		if(field instanceof InstVarDecl){
		InstVarDecl instVar = (InstVarDecl)field;
		//////////////////////////////
		// Alle Variablendeklarationen (int a, b, c) durchgehen:
		//////////////////////////////
		for(int i=0; i<instVar.getDeclIdVector().size(); i++){
		DeclId id = (DeclId)instVar.getDeclIdVector().elementAt(i);
		CInstVarTypeAssumption assum = new CInstVarTypeAssumption(this.getName(), id.get_Name(), instVar.getType(), instVar.getLineNumber(),instVar.getOffset(),new Vector<Integer>());  // Typannahme bauen...
		V_fields_methods.add(assum);  // ...und hinzuf�gen.
		}
		}
		}
		
		for(FieldDecl field : body.get_FieldDeclVector())
		{
		//////////////////////////////
		// Methode:
		//////////////////////////////
		if(field instanceof Method){
		Method method = (Method)field;
		//if(method.get_Method_Name().equals(this.getName()) && ((method.getReturnType().equals(new mycompiler.mytype.Void(0))) || method.getReturnType() instanceof TypePlaceholder)){
		if(method.get_Method_Name().equals(this.getName()) ){
				method.set_Method_Name("<init>");
		}
		//hoth: 06.04.2006
		//durchlaufe Block und suche nach Objektvariablen fuer Offset-Markierung
		Iterator<CTypeAssumption> fieldVarIterator = V_fields_methods.iterator();
		while (fieldVarIterator.hasNext()) 
		{
		//Wenn ObjektVariable
		CTypeAssumption dieAssum = fieldVarIterator.next();
		if(dieAssum instanceof CInstVarTypeAssumption)
		{
		  Class.isFirstLocalVarDecl=false; 
		  if(method.get_Block() != null)
			  method.get_Block().addOffsetsToAssumption(dieAssum,dieAssum.getIdentifier(),true);  
		}
		}
		
		methodList.addElement(method);
		
		// F�r V_fields_methods:
		CMethodTypeAssumption methodAssum = new CMethodTypeAssumption(this.getType(), method.get_Method_Name(), method.getReturnType(), method.getParameterCount(),method.getLineNumber(),method.getOffset(),new Vector<Integer>(),method.getGenericMethodParameters());  // Typannahme bauen...
		
		
		// Methode in V_Fields_methods ablegen
		// Dabei wird die OverloadedMethodID ermittelt !!
		// => Method setzenuct
		
		
		V_fields_methods.add(methodAssum);               
		method.setOverloadedID(methodAssum.getHashSetKey().getOverloadedMethodID());                
		
		
		// F�r die V_i:
		CTypeAssumptionSet localAssum = new CTypeAssumptionSet();
		
		// Bauen...
		ParameterList parameterList = method.getParameterList();
		if(parameterList!=null){
		for(int i=0; i<parameterList.sc_get_Formalparalist().size(); i++){
		    FormalParameter para = parameterList.sc_get_Formalparalist().elementAt(i);
		    // F�r V_fields_methods:
		    CParaTypeAssumption paraAssum = new CParaTypeAssumption(this.getName(), method.get_Method_Name(), method.getParameterCount(), method.getOverloadedID(),para.get_Name(), para.getType(), para.getLineNumber(),para.getOffset(),new Vector<Integer>());
		    //fuege Offsets fuer Parameter hinzu, hoth: 06.04.2006
		    Class.isFirstLocalVarDecl=false;
		    
		    if(method.get_Block() != null)
		    	method.get_Block().addOffsetsToAssumption(paraAssum,paraAssum.getIdentifier(),true);
		    
		    methodAssum.addParaAssumption(paraAssum);
		    
		        
		    
		
		    // F�r die V_i:
		    CLocalVarTypeAssumption varAssum = new CLocalVarTypeAssumption(this.getName(), method.get_Method_Name(), method.getParameterCount(), method.getOverloadedID(),"1", para.get_Name(),para.getType(), para.getLineNumber(),para.getOffset(),new Vector<Integer>());
		    localAssum.addElement(varAssum);
		    rememberLocals.addElement(varAssum);
		}
		}               
		// ...und hinzuf�gen:
		            
		V.addElement(localAssum);
		}
		}
		
		this.methodList = methodList;
		return methodList;
	}

    /**
     * Die Funktion ist erst nach dem Aufruf von getMethodList() nutzbar.
     * Ermittelt alle Felder und Methoden der Klasse und Erstellt eine Assumption f�r diese.
     * @return Die erstellten TypeAssumptions
     */
	private TypeAssumptions getTypeAssumptions() {
		if(this.typeAssumptions != null)return this.typeAssumptions; //Das sorgt daf�r, dass die Assumptions nur einmalig generiert werden.
    	TypeAssumptions assumptions = new TypeAssumptions(this.getName());
		this.getMethodList(); //Diese Funktion muss zuerst ausgef�hrt werden.
		//Assumption f�r this, also die aktuelle Klasse: (ist nicht mehr n�tig, da jedes AssumptionSet einer Klasse (dem namen einer Klasse) zugewiesen ist.
		//CLocalVarTypeAssumption thisAssumption = new CLocalVarTypeAssumption(this.name, name, 0, 0, name, "this", new RefType(name,0), 0, 0, null);
		//assumptions.setThisV(thisAssumption);
		
		for(FieldDecl field : body.get_FieldDeclVector()){
			assumptions.add(field.createTypeAssumptions(this));
		}
		
		//Eine Assumption f�r den Standardkonstruktor:
		// (Ein Standardkonstruktor wird immer angef�gt, da es momentan keine statischen Klassen gibt)
		if(assumptions.getMethodAssumptions(this.getName(), "<init>").size()==0){ //Falls kein Konstruktor f�r diese Klasse definiert wurde:
			assumptions.addMethodAssumption(new RefType(this.getName(),0), "<init>", new RefType(this.getName(),0), new Vector<CParaTypeAssumption>());
		}
		
		
		typinferenzLog.debug("Erstellte Assumptions: "+assumptions);
		
		this.typeAssumptions = assumptions; //Diese m�ssen anschlie�end nicht wieder generiert werden.
		return assumptions;
}
	
	public ConstraintsSet TYPE(Vector<Method> methodList, Vector<Expr> fielddeclarationList, TypeAssumptions assumptions){
    	ConstraintsSet ret = new ConstraintsSet();
    	// Die Felddeklarationen werden zu den Assumptions hinzugef�gt und gelten danach f�r jede Methode.
    	//TypeAssumptions assumptionsPlusFieldAssumptions = new TypeAssumptions(assumptions);
    	for(Expr expr : fielddeclarationList){
    		//ret.add(expr.TYPEStmt(assumptionsPlusFieldAssumptions));
    		ret.add(expr.TYPEStmt(assumptions));
    	}
    	for(Method methode : methodList){
    		//ret.add(methode.TYPE(assumptionsPlusFieldAssumptions));
    		ret.add(methode.TYPE(assumptions));
    	}
    	return ret;
    }
    
    // ino.method.clear.23113.defdescription type=javadoc
    /**
     * Entfernt Annahmen f�r lokale Variablen, die f�r Methodenparameter erzeugt       
     * worden sind. (siehe Algorithmus 5.17 TRProg, Martin Pl�micke)
     * <br/>Author: J�rg B�uerle
     * @param V
     * @param locals
     */
    // ino.end
    // ino.method.clear.23113.definition 
    void clear(CTypeAssumptionSet V, Vector<CTypeAssumption> locals)
    // ino.end
    // ino.method.clear.23113.body 
    {
        Iterator<CTypeAssumption> localsIt = locals.iterator();
        while(localsIt.hasNext()){
            CTypeAssumption local = localsIt.next();
            CTypeAssumption assum = V.getElement(local.getHashSetKey());
            if(assum!=null){
                V.removeElement(local.getHashSetKey());
            }
        }
    }
    // ino.end
    
    // ino.method.RetType.23119.defdescription type=javadoc
    /**
     * Liefert den berechneten R�ckgabetyp f�r die �bergebene Methode zur�ck.<br/>
     * (siehe Algorithmus RetType, Martin Pl�micke)
     * <br/>Author: J�rg B�uerle
     * @param me
     * @param V
     * @return
     */
    // ino.end
    // ino.method.RetType.23119.definition 
    private Type RetType(Method me, CTypeAssumptionSet V)
    // ino.end
    // ino.method.RetType.23119.body 
    {
        CTypeAssumption assum = V.getElement(new CMethodKey(this.getName(), me.get_Method_Name(), me.getParameterCount(),me.getOverloadedID()));
        if(assum instanceof CMethodTypeAssumption){
            return ((CMethodTypeAssumption)assum).getAssumedType();
        }
        else return null;
    }
    // ino.end
    
    // ino.method.toString.23125.defdescription type=javadoc
     /**
      * <br/>Author: Martin Pl�micke
      * @return
      */
     // ino.end
    // ino.method.toString.23125.definition 
    public String toString()
    // ino.end
    // ino.method.toString.23125.body 
    {
        //return superclassid.toString() + body.toString();
    	    //geaendert PL 07-07-28
    		return name + body.toString();
    }
    // ino.end

    
    // ino.method.wandleRefTypeAttributes2GenericAttributes.23128.defdescription type=javadoc
    /**
     * Alle Methoden der Klassen �berpr�fen, ob sie als
     * RefType deklarierte Attribute haben, die aber GenericTypeVars sind
     * und ggf. ersetzen
     * 
     * Bsp.:
     * bei public E elementAt(i){...} wird E vorerst als RefType erkannt
     * 
     */
    // ino.end
    // ino.method.wandleRefTypeAttributes2GenericAttributes.23128.definition 
    public void wandleRefTypeAttributes2GenericAttributes()
    // ino.end
    // ino.method.wandleRefTypeAttributes2GenericAttributes.23128.body 
    {
        
        // Klassen ohne Body werden hier nicht durchsucht
        // (p.ex. BaseTypes)
        if(body==null)
            return;
        
        Vector fieldsAndMethods=body.get_FieldDeclVector();
        
        // Alle Methoden und Instanzvariablen durchgehen
        for(int i=0;i<fieldsAndMethods.size();i++){
            
            // Ist es eine Methode?
            if(fieldsAndMethods.get(i) instanceof Method){
                Method method=(Method)fieldsAndMethods.get(i);              
                method.wandleRefTypeAttributes2GenericAttributes(paralist);
            }// Ist es eine InstanzVariable?
            else if(fieldsAndMethods.get(i) instanceof InstVarDecl){
                InstVarDecl instVar=(InstVarDecl)fieldsAndMethods.get(i);
                Type type=instVar.getType();
                // Nur wenn es sich um ein RefType-Field handelt
                if(type instanceof RefType){
                    GenericTypeVar pendant=ClassHelper.findGenericType((RefType)type,paralist,null);
                    if(pendant!=null){  //Wenn generisch, dann modifizieren
                        instVar.setType(pendant);
                    }
                }
            }           
        }
    }
    // ino.end

    
//    private void removeOldLocalVars(CTypeAssumptionSet V_i, CTypeAssumptionSet V_last){
//        Enumeration<IHashSetKey> enumer = V_last.getHashtable().keys();
//        while(enumer.hasMoreElements()){
//            CTypeAssumption currentAssum = V_last.getElement(enumer.nextElement());
//            if(currentAssum instanceof CLocalVarTypeAssumption){
//                V_i.removeElement(currentAssum);
//            }
//        }
//
//    }
    
    // ino.method.addOffsetsToAssumption.23131.defdescription type=javadoc
    /**
     * Methode f�gt zu einer CTypeAssumption alle
     * Offsets hinzu, wo die Variable benutzt wird. 
     * <br/>Author: Thomas Hornberger 07.04.2006
     * <br/>Author: Arne L�dtke 20.01.2007, Auf Polymorphie erweitert.
     * Wird nicht mehr verwendet. In Block ausgelagert.
     * @return
     */
    // ino.end
    // ino.method.addOffsetsToAssumption.23131.definition 
    public static void addOffsetsToAssumption(CTypeAssumption localAssumption, Block localBlock,String NameVariable,boolean isMemberVariable)
    // ino.end
    // ino.method.addOffsetsToAssumption.23131.body 
    {
      /*if(localBlock!=null){
      for(Object vectorObjekt : localBlock.statements) //durchlaufe alle Statements dieses Blocks
      {
        if(vectorObjekt instanceof Block) //Bei Block
         {
            Block b = (Block)vectorObjekt;
            addOffsetsToAssumption(localAssumption,b,NameVariable,isMemberVariable);//rekursiver Aufruf   
         }
        else 
        {   
            String Name_Superklasse = vectorObjekt.getClass().getSuperclass().getSimpleName();
            if(Name_Superklasse.equals("Statement"))  //Bei Statement
              {
                Statement s = (Statement)vectorObjekt;
                try{
                if(addOffsetsToStatement(localAssumption,s,NameVariable,isMemberVariable)==false)
                {break;}}
                catch(NullPointerException NPE){}
              }
            else if(Name_Superklasse.equals("Expr") || Name_Superklasse.equals("BinaryExpr") || Name_Superklasse.equals("UnaryExpr"))  //Bei Expression
              {
                Expr e = (Expr)vectorObjekt;
                try{
                addOffsetsToExpression(localAssumption,e,NameVariable,isMemberVariable);}
                catch(NullPointerException NPE){}         
             }
        }
        
      }}*/
    }
    // ino.end
    
    // ino.method.addOffsetsToStatement.23134.defdescription type=javadoc
    /**
     * Hilfs-Methode f�r die Offset-Zuweisung
     * durchsucht ein Statement rekursiv
     * <br/>Author: Thomas Hornberger 08.04.2006
     * <br/>Author: Arne L�dtke 20.10.2007, Auf Polymorphie umgebaut.
     * @return
     */
    // ino.end
    // ino.method.addOffsetsToStatement.23134.definition 
    public static boolean addOffsetsToStatement(CTypeAssumption localAssumption,Statement statement, String NameVariable, boolean isMemberVariable)
    // ino.end
    // ino.method.addOffsetsToStatement.23134.body 
    {
    	return statement.addOffsetsToStatement(localAssumption,NameVariable,isMemberVariable);
        /*if(statement instanceof Block) //Wenn Block
        {
          Block b = (Block)statement;
          addOffsetsToAssumption(localAssumption,b,NameVariable,isMemberVariable);
        }
        else if(statement instanceof IfStmt)//Wenn if
        {
          IfStmt i = (IfStmt)statement;
          addOffsetsToExpression(localAssumption,i.expr,NameVariable,isMemberVariable);
          addOffsetsToStatement(localAssumption,i.else_block,NameVariable,isMemberVariable);
          addOffsetsToStatement(localAssumption,i.then_block,NameVariable,isMemberVariable);
        }
        else if(statement instanceof Return)//Wenn Return
        {
          Return r = (Return)statement;
          addOffsetsToExpression(localAssumption,r.retexpr,NameVariable,isMemberVariable);
        }
        else if(statement instanceof WhileStmt)//Wenn While
        {
          WhileStmt w = (WhileStmt)statement;
          addOffsetsToExpression(localAssumption,w.expr,NameVariable,isMemberVariable);
          addOffsetsToStatement(localAssumption,w.loop_block,NameVariable,isMemberVariable);
        }
        else if(statement instanceof LocalVarDecl)//Wenn Lokale-Variable-Deklaration
        {
           isMemberVariable=true;//hoth 02.05.06
           if(isMemberVariable)//Wenn Objektvariable 
           {
               LocalVarDecl l = (LocalVarDecl)statement;
               if(l.get_Name().equals(NameVariable))
               {
                   if(isFirstLocalVarDecl==false)
                   {return false;}//Wenn jetzt lokale Variable kommt, dann springe raus
                   else
                   {isFirstLocalVarDecl=false;}
               }
           }
        }
        return true;*/
    }
    // ino.end
    
    // ino.method.addOffsetsToExpression.23137.defdescription type=javadoc
    /**
     * Hilfs-Methode f�r die Offset-Zuweisung
     * durchsucht eine Expression rekursiv
     * <br/>Author: Thomas Hornberger 07.04.2006
     * <br/>Authos: Arne L�dtke 20.01.2007, Auf Polymorphie umgebaut.
     * @return
     */
    // ino.end
    // ino.method.addOffsetsToExpression.23137.definition 
    public static void addOffsetsToExpression(CTypeAssumption localAssumption,Expr expression, String NameVariable,boolean isMemberVariable)
    // ino.end
    // ino.method.addOffsetsToExpression.23137.body 
    {   
        expression.addOffsetsToExpression(localAssumption,NameVariable,isMemberVariable);
    }
    // ino.end

    // ino.method.getSimpleName.23140.defdescription type=javadoc
    /**
     * HOTI
     * Liefert bei Klassen die fullyQualified angegeben wurden
     * nur den schlussendlichen Bezeichner
     * p.ex. java.util.Vector => Vector
     * @return
     */
    // ino.end
    // ino.method.getSimpleName.23140.definition 
    public String getSimpleName()
    // ino.end
    // ino.method.getSimpleName.23140.body 
    {
        return UsedId.createFromQualifiedName(getName(),-1).getSimpleName();
    }
    // ino.end

    public String getTypeInformation(Vector<Method> methodList, Vector<Expr> fieldList){
    	String ret = this.name+": ";
    	for(Expr field : fieldList){
    		ret+=field.getTypeInformation()+"\n";
    	}
    	for(Method m : methodList){
    		ret+=m.getTypeInformation()+"\n";
    	}
    	return ret;
    }
    
    
    /**
     * Generiert den JavaCode dieser Klasse im Falle f�r das �bergebene resultSet.
     * Dem ResultSet entsprechend werden in diesem Java-Code die TypePlaceholder durch die in ResultSet stehenden Typen ersetzt.
     * @return Java-Sourcefile
     */
    public String printJavaCode(TypeinferenceResultSet reconstructionResult){
    	JavaCodeResult ret = new JavaCodeResult("class ");

    	

    	
    	//Generiere JavaCode der extends-Typen:
    	/*
    	String containedTypesJavaCode = "";
    	for(Type containedType : containedTypes){
    		containedTypesJavaCode += containedType.printJavaCode(resultSet)+ ", ";
    	}
    	if(containedTypesJavaCode.length()>1)containedTypesJavaCode = containedTypesJavaCode.substring(0, containedTypesJavaCode.length() -2);
    	*/
    	
    	JavaCodeResult classBodyCode = new JavaCodeResult();
    	if(this.modifiers!=null)classBodyCode.attach(this.modifiers.printJavaCode(reconstructionResult.getUnifiedConstraints())).attach(" ");
    	
    	if(superclassid == null || superclassid.get_Name().size()<1){
    		int superclassidOffset = superclassid == null ? 0 : superclassid.getOffset();
    		superclassid = new UsedId("Object", superclassidOffset);
    	}
    
    	classBodyCode.attach(this.name + " extends ").attach(superclassid.printJavaCode(reconstructionResult.getUnifiedConstraints())).attach("\n");
    	JavaCodeResult bodyString = this.body.printJavaCode(reconstructionResult.getUnifiedConstraints()).attach("\n");
    	classBodyCode.attach(bodyString);
    	
    	//Zuerst die generischen Parameter f�r diese Klasse berechnen:
    	this.createGenericTypeVars(classBodyCode.getUnresolvedTPH());
    	
    	if(this.genericClassParameters != null && this.genericClassParameters.size()>0){
        	ret.attach("<");
        	
        	Iterator<GenericTypeVar> it = this.genericClassParameters.iterator();
        	while(it.hasNext()){
        		GenericTypeVar tph = it.next();
        		ret.attach(tph.printJavaCode(reconstructionResult.getUnifiedConstraints()));
        		if(it.hasNext())ret.attach(", ");
        	}
        	ret.attach(">");
    	}
    	
    	String stringReturn = ret.attach(classBodyCode).toString();
    	
    	return stringReturn;
    }
    
    /**
     * Errechnet die Generischen Parameter der Klasse f�r diese Klasse.
     * Die berechneten Variablen werden anschlie�end in die this.genericTypeVars eingesetzt. Dabei werden alte genericTypeVars �berschrieben.
     * @param tphs : Alle �briggebliebenen TypePLaceholder
     */
    public void createGenericTypeVars(Vector<TypePlaceholder> tphs){
    	this.genericClassParameters = new Vector<GenericTypeVar>();
    	for(TypePlaceholder tph : tphs){
    		GenericTypeVar toAdd = new GenericTypeVar(tph);
    		if(!this.genericClassParameters.contains(toAdd))this.genericClassParameters.add(toAdd);
    	}
    }
    
    /**
     * Errechnet die Generischen Parameter der Klasse f�r diese Klasse.
     * Die berechneten Variablen werden anschlie�end in die this.genericTypeVars eingesetzt. Dabei werden alte genericTypeVars �berschrieben.
     * @param reconstructionResult
     */
    public void createGenericTypeVars(TypeinferenceResultSet reconstructionResult){
    	this.genericClassParameters = new Vector<GenericTypeVar>();
    	for(Pair pair : reconstructionResult.getUnifiedConstraints()){
    		if(pair.TA2 instanceof TypePlaceholder && pair.TA1 instanceof TypePlaceholder){//    		if(pair.OperatorSmallerExtends() || pair.OperatorSmaller()){
    	    	Type ta1=reconstructionResult.getUnifiedConstraints().getTypeEqualTo(pair.TA1);
    	    	Type ta2=reconstructionResult.getUnifiedConstraints().getTypeEqualTo(pair.TA2);
    	    	this.genericClassParameters.add(new GenericTypeVar(new Pair(ta1,ta2)));
    		}
    		/*
    		// Auf SuperWildcardTypes �berpr�fen:
    		ArrayList<SuperWildcardType> wildcardTypes = pair.TA2.getSuperWildcardTypes();
    		wildcardTypes.addAll(pair.TA1.getSuperWildcardTypes());
    		for(SuperWildcardType wildcardType : wildcardTypes){
    			this.genericClassParameters.add(new GenericTypeVar(new Pair(TypePlaceholder.fresh(), wildcardType.getContainedType())));
    		}
    		*/
    	}
    	
    	for(Pair pair : reconstructionResult.getConstraints()){
    		if( ! reconstructionResult.getUnifiedConstraints().contains(pair.TA1)){
    			this.genericClassParameters.add(new GenericTypeVar(pair.TA1));
    		}
    		if( ! reconstructionResult.getUnifiedConstraints().contains(pair.TA2)){
    			this.genericClassParameters.add(new GenericTypeVar(pair.TA2));
    		}
    	}
    }

    /**
     * Erstellt einen RefType, welcher auf diese Klasse verweist
     * @return
     */
	public RefType getType() {
		return new RefType(this.getName(), this.get_ParaList(), 0);
	}

	
	/**
	 * Ermittelt die Sichtbaren Felder und Methoden der Klasse.
	 * (Momentan sind im Projekt alle Felder und Methoden "package private", da der Parser keine Access-Modifier einlesen kann.
	 * @return
	 */
	public TypeAssumptions getPublicFieldAssumptions() {
		TypeAssumptions ret = this.getTypeAssumptions();
		return ret;
	}
    
}
// ino.end