//This class has been generated automatically. Do not modify it by hand!
package org.etsi.t3q.visitor;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import de.ugoe.cs.swe.trex.core.analyzer.rfparser.LocationAST;
import de.ugoe.cs.swe.trex.core.analyzer.rfparser.TTCN3ParserTokenTypes;
//import de.ugoe.cs.swe.t3simexec.exceptions.TTCN3BehaviorException;
import org.etsi.t3q.exceptions.TTCN3BehaviorException;

public abstract class AbstractVisitor {

    public int visitedNodeCount;

    $nodeType:VisitMethod(); separator="\n"$

    public ContinueStatus visit(LocationAST node) throws TTCN3BehaviorException {
        visitedNodeCount++;
        ContinueStatus continueStatus;
        switch(node.getType()) {
            $nodeType:VisitCase(); separator="\n"$
        }
        return new ContinueStatus();
    }

    public abstract void init();
    public abstract void finish();
    
    public void acceptDFS(LocationAST node) throws TTCN3BehaviorException {
        init();
        searchASTDepthFirst(node);
        finish();
    }

    public void acceptBFS(LocationAST node) throws TTCN3BehaviorException {
        init();
        searchASTBreadthFirst(node);
        finish();
    }

    protected ContinueStatus searchASTDepthFirst(LocationAST node) throws TTCN3BehaviorException {
        if (node == null)
            return ContinueStatus.getInstance(true, true);

        LocationAST next = node;
        while (next != null) {
            ContinueStatus continueStatus = visit(next);
            if (!continueStatus.continueSearch)
                return ContinueStatus.getInstance(false, false);
            if (continueStatus.goDeeper)
                searchASTDepthFirst(next.getFirstChild());
            next = next.getNextSibling();
        }
        return ContinueStatus.getInstance(true, true);
    }

    protected ContinueStatus searchASTBreadthFirst(LocationAST node) throws TTCN3BehaviorException {
        if (node == null)
            return ContinueStatus.getInstance(true, true);
        
        Queue<LocationAST> open = new LinkedList<LocationAST>();
        open.add(node);
        searchASTBreadthFirst(open);
        return ContinueStatus.getInstance(true, true);
    }

    private ContinueStatus searchASTBreadthFirst(Queue<LocationAST> nodes) throws TTCN3BehaviorException {
        Queue<LocationAST> open = new LinkedList<LocationAST>();
        Iterator<LocationAST> it = nodes.iterator();
        while (it.hasNext()) {
            LocationAST item = it.next();
            while (item != null) {
                ContinueStatus continueStatus = visit(item);
                if (!continueStatus.continueSearch)
                    return ContinueStatus.getInstance(false, false);
                if ( (item.getFirstChild() != null) && (continueStatus.goDeeper) )
                    open.add(item.getFirstChild());
                item = item.getNextSibling();
            }
        }
        if (open.size() > 0)
            searchASTBreadthFirst(open);
        return ContinueStatus.getInstance(true, true);
    }

    static class ContinueStatus {
        public boolean continueSearch = true;
        public boolean goDeeper = true;
        private static ContinueStatus truetrue = new ContinueStatus(true, true);
        private static ContinueStatus truefalse = new ContinueStatus(true, false);
        private static ContinueStatus falsetrue = new ContinueStatus(false, true);
        private static ContinueStatus falsefalse = new ContinueStatus(false, false);

        private ContinueStatus() {
            this.continueSearch = true;
            this.goDeeper = true;
        }

        private ContinueStatus(boolean continueSearch, boolean goDeeper) {
            this.continueSearch = continueSearch;
            this.goDeeper = goDeeper;
        }

        public static ContinueStatus getInstance(boolean continueSearch, boolean goDeeper) {
            if (continueSearch && goDeeper) {
                return truetrue;
            } else if (!continueSearch && goDeeper) {
                return falsetrue;
            } else if (continueSearch && !goDeeper) {
                return truefalse;
            } else {
                return falsefalse;
            }
        }
    }
    

}