package org.incava.doctorj;

import java.util.Iterator;
import java.util.List;
import org.incava.analysis.Analyzer;
import org.incava.analysis.Report;
import org.incava.java.Java14ParserConstants;
import org.incava.java.SimpleNode;
import org.incava.java.Token;
import org.incava.log.Log;


/**
 * Analyzes Javadoc and code.
 */
public class DocAnalyzer extends Analyzer
{
    protected final static int CHKLVL_DOC_EXISTS = 0;
    
    protected final static int CHKLVL_TAG_CONTENT = 0;

    public DocAnalyzer(Report r)
    {
        super(r);
    }

    public boolean hasPublicAccess(SimpleNode node)
    {
        return hasLeadingToken(node, Java14ParserConstants.PUBLIC);
    }

    public boolean isAbstract(SimpleNode node)
    {
        return hasLeadingToken(node, Java14ParserConstants.ABSTRACT);
    }

    public boolean hasProtectedAccess(SimpleNode node)
    {
        return hasLeadingToken(node, Java14ParserConstants.PROTECTED);
    }

    public boolean hasPackageAccess(SimpleNode node)
    {
        return !hasPublicAccess(node) && !hasProtectedAccess(node) && !hasPrivateAccess(node);
    }

    public boolean hasPrivateAccess(SimpleNode node)
    {
        return hasLeadingToken(node, Java14ParserConstants.PRIVATE);
    }

    public boolean isCheckable(SimpleNode node, int level)
    {
        return ((Options.warningLevel >= level     && (hasPublicAccess(node) || isAbstract(node))) ||
                (Options.warningLevel >= level + 1 && (hasProtectedAccess(node)))                  ||
                (Options.warningLevel >= level + 2 && (hasPackageAccess(node)))                    ||
                (Options.warningLevel >= level + 3 && (hasPrivateAccess(node))));
    }

    /**
     * Returns whether this node has a matching token, occurring prior to any
     * non-tokens (i.e., before any child nodes).
     */
    public boolean hasLeadingToken(SimpleNode node, int tokenType)
    {
        List     children = node.getChildren();
        Iterator cit      = children.iterator();
        
        while (cit.hasNext()) {
            Object childObj = cit.next();
            if (childObj instanceof Token) {
                if (((Token)childObj).kind == tokenType) {
                    return true;
                }
            }
            else {
                break;
            }
        }
        return false;
    }
    
}
