/*
 * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
 * (license2)
 * Initial Developer: H2 Group
 */
package org.h2.tools.code;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * This tool checks that for each .java file there is a package.html file, 
 * that for each .java file there is at least one (class level) javadoc comment,
 * and that lines with comments are not too long.
 */
public class CheckJavadoc {

    private int errorCount;
    private static final int MAX_COMMENT_LINE_SIZE = 80;

    public static void main(String[] args) throws Exception {
        new CheckJavadoc().run();
    }

    void run() throws Exception {
        String baseDir = "src";
        check(new File(baseDir));
        if (errorCount > 0) {
            throw new Exception(errorCount + " errors found");
        }
    }

    private int check(File file) throws Exception {
        String name = file.getName();
        if (file.isDirectory()) {
            if (name.equals("CVS") || name.equals(".svn")) {
                return 0;
            }
            File[] list = file.listFiles();
            boolean foundPackageHtml = false, foundJava = false;
            for (int i = 0; i < list.length; i++) {
                int type = check(list[i]);
                if (type == 1) {
                    foundJava = true;
                } else if (type == 2) {
                    foundPackageHtml = true;
                }
            }
            if (foundJava && !foundPackageHtml) {
                System.out.println("No package.html file, but a Java file found at: " + file.getAbsolutePath());
                errorCount++;
            }
        } else {
            if (name.endsWith(".java")) {
                checkJavadoc(file);
                return 1;
            } else if (name.equals("package.html")) {
                return 2;
            }
        }
        return 0;
    }

    private void checkJavadoc(File file) throws IOException {
        RandomAccessFile in = new RandomAccessFile(file, "r");
        byte[] data = new byte[(int) file.length()];
        in.readFully(data);
        in.close();
        String text = new String(data);
        int comment = text.indexOf("/**");
        if (comment < 0) {
            System.out.println("No Javadoc comment: " + file.getAbsolutePath());
            errorCount++;
        }
        int open = text.indexOf('{');
        if (open < 0 || open < comment) {
            System.out.println("No '{' or '{' before the first Javadoc comment: " + 
                    file.getAbsolutePath());
            errorCount++;
        }
        int pos = 0;
        int lineNumber = 1;
        boolean inComment = false;
        while (true) {
            int next = text.indexOf("\n", pos);
            if (next < 0) {
                break;
            }
            String line = text.substring(pos, next).trim();
            if (line.startsWith("/*")) {
                inComment = true;
            }
            if (inComment) {
                if (line.length() > MAX_COMMENT_LINE_SIZE) {
                    System.out.println("Long line : " + file.getAbsolutePath()
                            + " (" + file.getName() + ":" + lineNumber + ")");
                    errorCount++;
                }                
                if (line.endsWith("*/")) {
                    inComment = false;
                }
            }
            if (!inComment && line.startsWith("//") && line.length() > MAX_COMMENT_LINE_SIZE) {
                System.out.println("Long line: " + file.getAbsolutePath()
                        + " (" + file.getName() + ":" + lineNumber + ")");
                errorCount++;
            }
            lineNumber++;
            pos = next + 1;
        }
    }

}
