package edu.neu.ccs.demeterf.demfgen;

import edu.neu.ccs.demeterf.*;
import edu.neu.ccs.demeterf.demfgen.classes.*;
import edu.neu.ccs.demeterf.lib.List;
import edu.neu.ccs.demeterf.lib.Option;
import edu.neu.ccs.demeterf.parallel.ParTraversal;
import edu.neu.ccs.demeterf.stackless.HeapTrav;

/** Represents a little traversal factory, so there's a central place to
 *    switch from reflective to static traversals. The traversal factories
 *    are placed in the following classes:
 *    <ul>
 *       <li><code>edu.neu.ccs.demeterf.demfgen.Factory</code></li>
 *       <li><code>edu.neu.ccs.demeterf.demfgen.traversals.Travs</code></li>
 *       <li><code>edu.neu.ccs.demeterf.demfgen.dgp.traversals.Travs</code></li>
 *    </ul>
 */
public abstract class Factory{
    //** What kind of traversal...
    static Factory fact = new DynFactory();
    //static Factory fact = new StaticFactory();
    //static Factory fact = new ParFactory();
    //static Factory fact = new HeapFactory();
    
    public static DFGTrav newTraversal(FC f){ return fact.newTrav(f); }
    public static DFGTrav newTraversal(FC f, Control c){ return fact.newTrav(f, c); } 
    public static DFGTravC newTraversalCtx(FC f){ return fact.newTravCtx(f); }
    public static DFGTravC newTraversalCtx(FC f, Control c){ return fact.newTravCtx(f, c); } 

    public abstract DFGTrav newTrav(FC f);
    public abstract DFGTrav newTrav(FC f, Control c);
    public abstract DFGTravC newTravCtx(FC f);
    public abstract DFGTravC newTravCtx(FC f, Control c);
    
    private static class DynFactory extends Factory{
        public DFGTrav newTrav(FC f){ return new Trav(f); }
        public DFGTrav newTrav(FC f, Control c){ return new Trav(f,c); }
        public DFGTravC newTravCtx(FC f){ return new Trav(f); }
        public DFGTravC newTravCtx(FC f, Control c){ return new Trav(f,c); }
    }
    private static class StaticFactory extends Factory{
        public DFGTrav newTrav(FC f){ return new STrav(f); }
        public DFGTrav newTrav(FC f, Control c){ return new STrav(f,c); }
        public DFGTravC newTravCtx(FC f){ return new STravC(f); }
        public DFGTravC newTravCtx(FC f, Control c){ return new STravC(f,c); }
    }
    private static class ParFactory extends Factory{
        public DFGTrav newTrav(FC f){ return new PTrav(f); }
        public DFGTrav newTrav(FC f, Control c){ return new PTrav(f,c); }
        public DFGTravC newTravCtx(FC f){ return new PTrav(f); }
        public DFGTravC newTravCtx(FC f, Control c){ return new PTrav(f,c); }
    }
    private static class HeapFactory extends Factory{
        public DFGTrav newTrav(FC f){ return new HTrav(f); }
        public DFGTrav newTrav(FC f, Control c){ return new HTrav(f,c); }
        public DFGTravC newTravCtx(FC f){ return new HTrav(f); }
        public DFGTravC newTravCtx(FC f, Control c){ return new HTrav(f,c); }
    }
    static class Trav implements DFGTrav,DFGTravC{
        Traversal trav;
        Trav(FC f){ this(new Traversal(f)); }
        Trav(FC f, Control c){ this(new Traversal(f,c)); }
        Trav(Traversal t){ trav = t; }
        public <Ret> Ret traverseList_CDFile_(List<CDFile> o){ return trav.<Ret>traverse(o); }
        public <Ret> Ret traverseTypeDefParams(TypeDefParams o){ return trav.<Ret>traverse(o); }
        public <Ret> Ret traverseTypeDefList(TypeDefList o){ return trav.<Ret>traverse(o); }
        public <Ret> Ret traverseList_TypeDef_(List<TypeDef> o){ return trav.<Ret>traverse(o); }
        public <Ret> Ret traverseList_FieldOrSyntax_(List<FieldOrSyntax> o){ return trav.<Ret>traverse(o); }
        public <Ret> Ret traverseOption_List_TypeDef__(Option<List<TypeDef>> o){ return trav.<Ret>traverse(o); }
        public <Ret> Ret traverseTypeDef(TypeDef o){ return trav.<Ret>traverse(o); }
        public <Ret> Ret traverseIncludeList(IncludeList o){ return trav.<Ret>traverse(o); }
        // Contexts...
        public <Ret> Ret traverseList_FieldOrSyntax_(List<FieldOrSyntax> o, Object a){ return trav.<Ret>traverse(o,a); }
        public <Ret> Ret traverseList_CDFile_(List<CDFile> o, Object a){ return trav.<Ret>traverse(o,a); }
        public <Ret> Ret traverseTypeDefList(TypeDefList o, Object a){ return trav.<Ret>traverse(o,a); }
        public <Ret> Ret traverseTypeDef(TypeDef o, Object a){ return trav.<Ret>traverse(o,a); }
    }
    static class PTrav extends Trav{
        PTrav(FC f){ super(new ParTraversal(f)); }
        PTrav(FC f, Control c){ super(new ParTraversal(f,c)); }
    }
    static class HTrav extends Trav{
        HTrav(FC f){ super(new HeapTrav(f)); }
        HTrav(FC f, Control c){ super(new HeapTrav(f,c)); }
    }
    static class STrav extends StaticTrav implements DFGTrav{
        STrav(FC f){ super(f); }
        STrav(FC f, Control c){ super(f,c); }
    }
    static class STravC extends StaticTravCtx implements DFGTravC{
        STravC(FC f){ super(f); }
        STravC(FC f, Control c){ super(f,c); }
    }
    
}