package org.asciidoctor.asciidoclet;

import com.sun.javadoc.*;

import java.io.*;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * Iterates over the various elements of a RootDoc, handing off to the DocletRenderer to perform the rendering work.
 *
 * @author John Ericksen
 */
public class DocletIterator {

    /**
     * Renders a RootDoc's contents.
     *
     * @param rootDoc
     * @param renderer
     */
    public boolean render(RootDoc rootDoc, DocletRenderer renderer) {
        if (!processOverview(rootDoc, renderer)) return false;
        Set<PackageDoc> packages = new HashSet<PackageDoc>();
        for (ClassDoc doc : rootDoc.classes()) {
            packages.add(doc.containingPackage());
            renderClass(doc, renderer);
        }
        for (PackageDoc doc : packages) {
            renderer.renderDoc(doc);
        }
        return true;
    }

    /**
     * Renders an individual class.
     *
     * @param doc input
     */
    private void renderClass(ClassDoc doc, DocletRenderer renderer) {
        //handle the various parts of the Class doc
        renderer.renderDoc(doc);
        for ( MemberDoc member : doc.fields() ) {
            renderer.renderDoc(member);
        }
        for ( MemberDoc member : doc.constructors() ) {
            renderer.renderDoc(member);
        }
        for ( MemberDoc member : doc.methods() ) {
            renderer.renderDoc(member);
        }
        for ( MemberDoc member : doc.enumConstants() ) {
            renderer.renderDoc(member);
        }
        if ( doc instanceof AnnotationTypeDoc) {
            for ( MemberDoc member : ((AnnotationTypeDoc)doc).elements() ) {
                renderer.renderDoc(member);
            }
        }
    }

    private boolean processOverview(RootDoc rootDoc, DocletRenderer renderer) {
        File overviewFile = getOverviewFile(rootDoc.options());
        if (overviewFile != null) {
            if (isAsciidocFile(overviewFile.getName())) {
                try {
                    String overviewContent = readFile(overviewFile, getEncoding(rootDoc.options()));
                    rootDoc.setRawCommentText(overviewContent);
                    renderer.renderDoc(rootDoc);
                } catch (IOException e) {
                    rootDoc.printError("Error reading overview file: " + e.getLocalizedMessage());
                    return false;
                }
            }
            else {
                rootDoc.printNotice("Skipping non-Asciidoc overview " + overviewFile + ", will be processed by standard doclet.");
            }
        }
        return true;
    }

    private File getOverviewFile(String[][] options) {
        for (String option[] : options) {
            if ("-overview".equals(option[0])) {
                return new File(option[1]);
            }
        }
        return null;
    }

    private Charset getEncoding(String[][] options) {
        for (String option[] : options) {
            if ("-encoding".equals(option[0])) {
                return Charset.forName(option[1]);
            }
        }
        return Charset.forName("UTF-8");
    }

    private static boolean isAsciidocFile(String name) {
        return ASCIIDOC_FILE_PATTERN.matcher(name).matches();
    }

    private static String readFile(File f, Charset charset) throws IOException {
        char[] buf = new char[1024];
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f), charset));
        try {
            StringBuilder out = new StringBuilder();
            int n;
            while ((n = reader.read(buf)) > 0) {
                out.append(buf, 0, n);
            }
            return out.toString();
        } finally {
            try {
                reader.close();
            } catch (IOException e) { }
        }
    }

    static final Pattern ASCIIDOC_FILE_PATTERN = Pattern.compile("(.*\\.(ad|adoc|txt|asciidoc))");
}

@@ -31,16 +31,91 @@
 oclet;%0A%0A
+import com.google.common.base.Charsets;%0Aimport com.google.common.io.Files;%0A
 import c
@@ -2121,32 +2121,103 @@
           try %7B%0A
+                    Charset encoding = getEncoding(rootDoc.options());%0A
                 
@@ -2245,24 +2245,30 @@
 ntent = 
-read
 File
+s.toString
 (overvie
@@ -2278,38 +2278,16 @@
 le, 
-getE
+e
 ncoding
-(rootDoc.options())
 );%0A 
@@ -3295,25 +3295,15 @@
 rset
-.forName(%22UTF-8%22)
+s.UTF_8
 ;%0A  
@@ -3360,24 +3360,24 @@
 ing name) %7B%0A
+
         retu
@@ -3437,584 +3437,8 @@
  %7D%0A%0A
-    private static String readFile(File f, Charset charset) throws IOException %7B%0A        char%5B%5D buf = new char%5B1024%5D;%0A        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f), charset));%0A        try %7B%0A            StringBuilder out = new StringBuilder();%0A            int n;%0A            while ((n = reader.read(buf)) %3E 0) %7B%0A                out.append(buf, 0, n);%0A            %7D%0A            return out.toString();%0A        %7D finally %7B%0A            try %7B%0A                reader.close();%0A            %7D catch (IOException e) %7B %7D%0A        %7D%0A    %7D%0A%0A
     

Use Guava's File.toString() to read overview file.