12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others.
22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
3bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert/**
4bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *******************************************************************************
5bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Copyright (C) 2004-2012, International Business Machines Corporation and    *
6bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * others. All Rights Reserved.                                                *
7bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *******************************************************************************
8bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */
9bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
10bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert/**
11bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Generate a list of ICU's public APIs, sorted by qualified name and signature
12bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * public APIs are all non-internal, non-package apis in com.ibm.icu.[lang|math|text|util].
13bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * For each API, list
14bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - public, package, protected, or private (PB PK PT PR)
15bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - static or non-static (STK NST)
16bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - final or non-final (FN NF)
17bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - synchronized or non-synchronized (SYN NSY)
18bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - stable, draft, deprecated, obsolete (ST DR DP OB)
19bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - abstract or non-abstract (AB NA)
20bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * - constructor, member, field (C M F)
21bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
22bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Requires JDK 1.4.2 or later
23bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
24bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Sample compilation:
25bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * c:/doug/java/jdk1.4.2/build/windows-i586/bin/javac *.java
26bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
27bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Sample execution
28bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * c:/j2sdk1.4.2/bin/javadoc
29bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -classpath c:/jd2sk1.4.2/lib/tools.jar
30bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -doclet com.ibm.icu.dev.tool.docs.GatherAPIData
31bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -docletpath c:/doug/cvsproj/icu4j/src
32bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -sourcepath c:/doug/cvsproj/icu4j/src
33bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -name "ICU4J 3.0"
34bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -output icu4j30.api
35bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -gzip
36bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -source 1.4
37bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   com.ibm.icu.lang com.ibm.icu.math com.ibm.icu.text com.ibm.icu.util
38bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
39bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * todo: provide command-line control of filters of which subclasses/packages to process
40bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * todo: record full inheritance heirarchy, not just immediate inheritance
41bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * todo: allow for aliasing comparisons (force (pkg.)*class to be treated as though it
42bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *       were in a different pkg/class heirarchy (facilitates comparison of icu4j and java)
43bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */
44bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
45bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpackage com.ibm.icu.dev.tool.docs;
46bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
47bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert// standard release sdk won't work, need internal build to get access to javadoc
48bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.BufferedWriter;
49bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.FileOutputStream;
50bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.IOException;
51bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.OutputStream;
52bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.io.OutputStreamWriter;
53bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.Collection;
54bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.Iterator;
55bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.TreeSet;
56bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.regex.Pattern;
57bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.zip.GZIPOutputStream;
58bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.zip.ZipEntry;
59bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport java.util.zip.ZipOutputStream;
60bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
61bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ClassDoc;
62bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ConstructorDoc;
63bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.Doc;
64bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ExecutableMemberDoc;
65bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.FieldDoc;
66bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.MethodDoc;
67bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ProgramElementDoc;
68bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.RootDoc;
69bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.Tag;
70bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
71bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpublic class GatherAPIDataOld {
72bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    RootDoc root;
73bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    TreeSet results;
74bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    String srcName = "Current"; // default source name
75bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    String output; // name of output file to write
76bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    String base; // strip this prefix
77bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    Pattern pat;
78bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean zip;
79bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean gzip;
80bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean internal;
81bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean version;
82bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
83bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public static int optionLength(String option) {
84bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (option.equals("-name")) {
85bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 2;
86bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-output")) {
87bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 2;
88bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-base")) {
89bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 2;
90bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-filter")) {
91bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 2;
92bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-zip")) {
93bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
94bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-gzip")) {
95bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
96bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-internal")) {
97bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
98bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-version")) {
99bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
100bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
101bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return 0;
102bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
103bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
104bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public static boolean start(RootDoc root) {
105bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return new GatherAPIDataOld(root).run();
106bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
107bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
108bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    GatherAPIDataOld(RootDoc root) {
109bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        this.root = root;
110bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
111bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String[][] options = root.options();
112bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < options.length; ++i) {
113bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            String opt = options[i][0];
114bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (opt.equals("-name")) {
115bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.srcName = options[i][1];
116bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-output")) {
117bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.output = options[i][1];
118bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-base")) {
119bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.base = options[i][1]; // should not include '.'
120bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-filter")) {
121bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.pat = Pattern.compile(options[i][1], Pattern.CASE_INSENSITIVE);
122bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-zip")) {
123bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.zip = true;
124bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-gzip")) {
125bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.gzip = true;
126bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-internal")) {
127bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.internal = true;
128bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-version")) {
129bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.version = true;
130bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
131bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
132bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
133bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        results = new TreeSet(APIInfo.defaultComparator());
134bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
135bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
136bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private boolean run() {
137bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        doDocs(root.classes());
138bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
139bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        OutputStream os = System.out;
140bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (output != null) {
141bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ZipOutputStream zos = null;
142bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            try {
143bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (zip) {
144bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    zos = new ZipOutputStream(new FileOutputStream(output + ".zip"));
145bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    zos.putNextEntry(new ZipEntry(output));
146bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    os = zos;
147bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } else if (gzip) {
148bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    os = new GZIPOutputStream(new FileOutputStream(output + ".gz"));
149bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } else {
150bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    os = new FileOutputStream(output);
151bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
152bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
153bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            catch (IOException e) {
154bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                RuntimeException re = new RuntimeException(e.getMessage());
155bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                re.initCause(e);
156bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                throw re;
157bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
158bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            finally {
159bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (zos != null) {
160bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    try {
161bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        zos.close();
162bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    } catch (Exception e) {
163bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // ignore
164bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
165bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
166bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
167bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
168bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
169bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        BufferedWriter bw = null;
170bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        try {
171bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
172bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw = new BufferedWriter(osw);
173bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
174bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // writing data file
175bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.write(String.valueOf(APIInfo.VERSION) + APIInfo.SEP); // header version
176bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.write(srcName + APIInfo.SEP); // source name
177bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.write((base == null ? "" : base) + APIInfo.SEP); // base
178bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.newLine();
179bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            writeResults(results, bw);
180bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.close(); // should flush, close all, etc
181bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } catch (IOException e) {
182bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            try { bw.close(); } catch (IOException e2) {}
183bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            RuntimeException re = new RuntimeException("write error: " + e.getMessage());
184bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            re.initCause(e);
185bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            throw re;
186bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
187bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
188bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return false;
189bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
190bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
191bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private void doDocs(ProgramElementDoc[] docs) {
192bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (docs != null && docs.length > 0) {
193bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (int i = 0; i < docs.length; ++i) {
194bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                doDoc(docs[i]);
195bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
196bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
197bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
198bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
199bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private void doDoc(ProgramElementDoc doc) {
200bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (ignore(doc)) return;
201bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
202bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isClass() || doc.isInterface()) {
203bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ClassDoc cdoc = (ClassDoc)doc;
204bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            doDocs(cdoc.fields());
205bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            doDocs(cdoc.constructors());
206bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            doDocs(cdoc.methods());
207bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            doDocs(cdoc.innerClasses());
208bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
209bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
210bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        APIInfo info = createInfo(doc);
211bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (info != null) {
212bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            results.add(info);
213bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
214bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
215bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
216bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private boolean ignore(ProgramElementDoc doc) {
217bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc == null) return true;
218bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isPrivate() || doc.isPackagePrivate()) return true;
219bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc instanceof ConstructorDoc && ((ConstructorDoc)doc).isSynthetic()) return true;
220bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.qualifiedName().indexOf(".misc") != -1) {
221bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            System.out.println("misc: " + doc.qualifiedName()); return true;
222bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
223bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (!internal) { // debug
224bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            Tag[] tags = doc.tags();
225bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (int i = 0; i < tags.length; ++i) {
226bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (tagKindIndex(tags[i].kind()) == INTERNAL) { return true; }
227bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
228bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
229bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (pat != null && (doc.isClass() || doc.isInterface())) {
230bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (!pat.matcher(doc.name()).matches()) {
231bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return true;
232bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
233bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
234bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return false;
235bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
236bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
237bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static void writeResults(Collection c, BufferedWriter w) {
238bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        Iterator iter = c.iterator();
239bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        while (iter.hasNext()) {
240bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            APIInfo info = (APIInfo)iter.next();
241bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.writeln(w);
242bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
243bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
244bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
245bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private String trimBase(String arg) {
246bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (base != null) {
247bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (int n = arg.indexOf(base); n != -1; n = arg.indexOf(base, n)) {
248bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                arg = arg.substring(0, n) + arg.substring(n+base.length());
249bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
250bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
251bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return arg;
252bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
253bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
254bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public APIInfo createInfo(ProgramElementDoc doc) {
255bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
256bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // Doc. name
257bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // Doc. isField, isMethod, isConstructor, isClass, isInterface
258bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ProgramElementDoc. containingClass, containingPackage
259bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ProgramElementDoc. isPublic, isProtected, isPrivate, isPackagePrivate
260bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ProgramElementDoc. isStatic, isFinal
261bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // MemberDoc.isSynthetic
262bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ExecutableMemberDoc isSynchronized, signature
263bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // Type.toString() // e.g. "String[][]"
264bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ClassDoc.isAbstract, superClass, interfaces, fields, methods, constructors, innerClasses
265bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // FieldDoc type
266bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ConstructorDoc qualifiedName
267bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // MethodDoc isAbstract, returnType
268bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
269bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        APIInfo info = new APIInfo();
270bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (version) {
271bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.includeStatusVersion(true);
272bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
273bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
274bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // status
275bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String[] version = new String[1];
276bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        info.setType(APIInfo.STA, tagStatus(doc, version));
277bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        info.setStatusVersion(version[0]);
278bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
279bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // visibility
280bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isPublic()) {
281bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setPublic();
282bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isProtected()) {
283bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setProtected();
284bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isPrivate()) {
285bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setPrivate();
286bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else {
287bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // default is package
288bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
289bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
290bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // static
291bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isStatic()) {
292bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setStatic();
293bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else {
294bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // default is non-static
295bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
296bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
297bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // final
298bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isFinal()) {
299bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setFinal();
300bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else {
301bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // default is non-final
302bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
303bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
304bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // type
305bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isField()) {
306bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setField();
307bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isMethod()) {
308bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setMethod();
309bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isConstructor()) {
310bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setConstructor();
311bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isClass() || doc.isInterface()) {
312bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setClass();
313bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
314bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
315bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        info.setPackage(trimBase(doc.containingPackage().name()));
316bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        info.setClassName((doc.isClass() || doc.isInterface() || (doc.containingClass() == null))
317bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                          ? ""
318bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                          : trimBase(doc.containingClass().name()));
319bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        info.setName(trimBase(doc.name()));
320bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
321bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc instanceof FieldDoc) {
322bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            FieldDoc fdoc = (FieldDoc)doc;
323bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setSignature(trimBase(fdoc.type().toString()));
324bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc instanceof ClassDoc) {
325bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ClassDoc cdoc = (ClassDoc)doc;
326bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
327bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (cdoc.isClass() && cdoc.isAbstract()) {
328bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                // interfaces are abstract by default, don't mark them as abstract
329bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setAbstract();
330bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
331bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
332bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            StringBuffer buf = new StringBuffer();
333bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (cdoc.isClass()) {
334bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                buf.append("extends ");
335bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                buf.append(cdoc.superclass().qualifiedName());
336bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
337bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ClassDoc[] imp = cdoc.interfaces();
338bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (imp != null && imp.length > 0) {
339bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (buf.length() > 0) {
340bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    buf.append(" ");
341bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
342bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                buf.append("implements");
343bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                for (int i = 0; i < imp.length; ++i) {
344bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (i != 0) {
345bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        buf.append(",");
346bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
347bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    buf.append(" ");
348bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    buf.append(imp[i].qualifiedName());
349bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
350bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
351bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setSignature(trimBase(buf.toString()));
352bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else {
353bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ExecutableMemberDoc emdoc = (ExecutableMemberDoc)doc;
354bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (emdoc.isSynchronized()) {
355bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setSynchronized();
356bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
357bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
358bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (doc instanceof MethodDoc) {
359bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                MethodDoc mdoc = (MethodDoc)doc;
360bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (mdoc.isAbstract()) {
361bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    info.setAbstract();
362bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
363bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setSignature(trimBase(mdoc.returnType().toString() + emdoc.signature()));
364bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else {
365bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                // constructor
366bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setSignature(trimBase(emdoc.signature()));
367bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
368bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
369bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
370bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return info;
371bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
372bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
373bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private int tagStatus(final Doc doc, String[] version) {
374bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        class Result {
375bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int res = -1;
376bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            void set(int val) {
377bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (res != -1) {
378bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (val == APIInfo.STA_DEPRECATED) {
379bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // ok to have both a 'standard' tag and deprecated
380bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        return;
381bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    } else if (res != APIInfo.STA_DEPRECATED) {
382bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // if already not deprecated, this is an error
383bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        System.err.println("bad doc: " + doc + " both: " + APIInfo.getTypeValName(APIInfo.STA, res) + " and: " + APIInfo.getTypeValName(APIInfo.STA, val));
384bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        return;
385bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
386bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
387bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                // ok to replace with new tag
388bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                res = val;
389bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
390bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int get() {
391bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (res == -1) {
392bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    System.err.println("warning: no tag for " + doc);
393bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    return 0;
394bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
395bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return res;
396bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
397bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
398bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
399bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        Tag[] tags = doc.tags();
400bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        Result result = new Result();
401bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String statusVer = "";
402bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < tags.length; ++i) {
403bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            Tag tag = tags[i];
404bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
405bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            String kind = tag.kind();
406bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int ix = tagKindIndex(kind);
407bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
408bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            switch (ix) {
409bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case INTERNAL:
410bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(internal ? APIInfo.STA_INTERNAL : -2); // -2 for legacy compatibility
411bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
412bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
413bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
414bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case DRAFT:
415bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(APIInfo.STA_DRAFT);
416bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
417bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
418bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
419bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case STABLE:
420bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(APIInfo.STA_STABLE);
421bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
422bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
423bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
424bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case DEPRECATED:
425bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(APIInfo.STA_DEPRECATED);
426bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
427bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
428bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
429bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case OBSOLETE:
430bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(APIInfo.STA_OBSOLETE);
431bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
432bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
433bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
434bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SINCE:
435bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case EXCEPTION:
436bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case VERSION:
437bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case UNKNOWN:
438bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case AUTHOR:
439bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SEE:
440bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case PARAM:
441bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case RETURN:
442bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case THROWS:
443bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SERIAL:
444bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
445bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
446bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            default:
447bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                throw new RuntimeException("unknown index " + ix + " for tag: " + kind);
448bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
449bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
450bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
451bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (version != null) {
452bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            version[0] = statusVer;
453bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
454bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return result.get();
455bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
456bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
457bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private String getStatusVersion(Tag tag) {
458bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String text = tag.text();
459bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (text != null && text.length() > 0) {
460bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // Extract version string
461bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int start = -1;
462bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int i = 0;
463bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (; i < text.length(); i++) {
464bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                char ch = text.charAt(i);
465bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (ch == '.' || (ch >= '0' && ch <= '9')) {
466bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (start == -1) {
467bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        start = i;
468bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
469bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } else if (start != -1) {
470bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    break;
471bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
472bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
473bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (start != -1) {
474bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return text.substring(start, i);
475bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
476bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
477bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return "";
478bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
479bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
480bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int UNKNOWN = -1;
481bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int INTERNAL = 0;
482bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int DRAFT = 1;
483bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int STABLE = 2;
484bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int SINCE = 3;
485bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int DEPRECATED = 4;
486bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int AUTHOR = 5;
487bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int SEE = 6;
488bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int VERSION = 7;
489bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int PARAM = 8;
490bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int RETURN = 9;
491bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int THROWS = 10;
492bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int OBSOLETE = 11;
493bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int EXCEPTION = 12;
494bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int SERIAL = 13;
495bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
496bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static int tagKindIndex(String kind) {
497bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        final String[] tagKinds = {
498bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            "@internal", "@draft", "@stable", "@since", "@deprecated", "@author", "@see", "@version",
499bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            "@param", "@return", "@throws", "@obsolete", "@exception", "@serial"
500bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        };
501bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
502bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < tagKinds.length; ++i) {
503bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (kind.equals(tagKinds[i])) {
504bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return i;
505bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
506bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
507bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return UNKNOWN;
508bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
509bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert}
510