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-2014, 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.5 or later
232d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert *
24bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Sample compilation:
25bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * c:/doug/java/jdk1.5/build/windows-i586/bin/javac *.java
26bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *
27bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Sample execution
28bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * c:/j2sdk1.5/bin/javadoc
292d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert *   -classpath c:/jd2sk1.5/lib/tools.jar
30bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -doclet com.ibm.icu.dev.tool.docs.GatherAPIData
31bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -docletpath c:/doug/icu4j/tools/build/out/lib/icu4j-build-tools.jar
322d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert *   -sourcepath c:/doug/icu4j/main/classes/core/src
33bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -name "ICU4J 4.2"
34bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -output icu4j42.api2
35bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -gzip
36bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *   -source 1.5
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
402d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * todo: record full inheritance hierarchy, not just immediate inheritance
412d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * todo: allow for aliasing comparisons (force (pkg.)*class to be treated as though it
42bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert *       were in a different pkg/class hierarchy (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.ExecutableMemberDoc;
64bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.FieldDoc;
65bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.LanguageVersion;
66bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.MemberDoc;
67bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.MethodDoc;
68bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.ProgramElementDoc;
69bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.RootDoc;
70bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.sun.javadoc.Tag;
71bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
72bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpublic class GatherAPIData {
73bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    RootDoc root;
74bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    TreeSet results;
75bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    String srcName = "Current"; // default source name
76bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    String output; // name of output file to write
77bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    String base; // strip this prefix
78bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    Pattern pat;
79bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean zip;
80bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean gzip;
81bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean internal;
82bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    boolean version;
83bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
84bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public static int optionLength(String option) {
85bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (option.equals("-name")) {
86bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 2;
87bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-output")) {
88bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 2;
89bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-base")) {
90bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 2;
91bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-filter")) {
92bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 2;
93bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-zip")) {
94bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
95bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-gzip")) {
96bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
97bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-internal")) {
98bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
99bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (option.equals("-version")) {
100bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return 1;
101bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
102bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return 0;
103bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
104bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
105bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public static boolean start(RootDoc root) {
106bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return new GatherAPIData(root).run();
107bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
108bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
109bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    /**
110bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert     * If you don't do this, javadoc treats enums like regular classes!
111bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert     * doesn't matter if you pass -source 1.5 or not.
112bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert     */
113bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public static LanguageVersion languageVersion() {
114bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return LanguageVersion.JAVA_1_5;
115bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
116bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
117bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    GatherAPIData(RootDoc root) {
118bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        this.root = root;
119bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
120bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String[][] options = root.options();
121bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < options.length; ++i) {
122bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            String opt = options[i][0];
123bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (opt.equals("-name")) {
124bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.srcName = options[i][1];
125bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-output")) {
126bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.output = options[i][1];
127bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-base")) {
128bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.base = options[i][1]; // should not include '.'
129bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-filter")) {
130bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.pat = Pattern.compile(options[i][1], Pattern.CASE_INSENSITIVE);
131bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-zip")) {
132bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.zip = true;
133bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-gzip")) {
134bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.gzip = true;
135bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-internal")) {
136bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.internal = true;
137bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else if (opt.equals("-version")) {
138bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                this.version = true;
139bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
140bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
141bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
142bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        results = new TreeSet(APIInfo.defaultComparator());
143bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
144bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
145bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private boolean run() {
146bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        doDocs(root.classes());
147bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
148bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        OutputStream os = System.out;
149bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (output != null) {
150bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ZipOutputStream zos = null;
151bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            try {
152bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (zip) {
153bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    zos = new ZipOutputStream(new FileOutputStream(output + ".zip"));
154bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    zos.putNextEntry(new ZipEntry(output));
155bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    os = zos;
156bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } else if (gzip) {
157bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    os = new GZIPOutputStream(new FileOutputStream(output + ".gz"));
158bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } else {
159bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    os = new FileOutputStream(output);
160bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
161bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
162bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            catch (IOException e) {
163bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                RuntimeException re = new RuntimeException(e.getMessage());
164bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                re.initCause(e);
165bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                throw re;
166bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
167bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            finally {
168bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (zos != null) {
169bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    try {
170bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        zos.close();
171bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    } catch (Exception e) {
172bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // ignore
173bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
174bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
175bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
176bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
177bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
178bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        BufferedWriter bw = null;
179bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        try {
180bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
181bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw = new BufferedWriter(osw);
182bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
183bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // writing data file
184bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.write(String.valueOf(APIInfo.VERSION) + APIInfo.SEP); // header version
185bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.write(srcName + APIInfo.SEP); // source name
186bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.write((base == null ? "" : base) + APIInfo.SEP); // base
187bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.newLine();
188bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            writeResults(results, bw);
189bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            bw.close(); // should flush, close all, etc
190bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } catch (IOException e) {
191bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            try { bw.close(); } catch (IOException e2) {}
192bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            RuntimeException re = new RuntimeException("write error: " + e.getMessage());
193bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            re.initCause(e);
194bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            throw re;
195bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
196bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
197bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return false;
198bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
199bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
200bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private void doDocs(ProgramElementDoc[] docs) {
201bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (docs != null && docs.length > 0) {
202bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (int i = 0; i < docs.length; ++i) {
203bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                doDoc(docs[i]);
204bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
205bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
206bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
207bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
208bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private void doDoc(ProgramElementDoc doc) {
209bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (ignore(doc)) return;
210bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
211bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isClass() || doc.isInterface()) {
212bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ClassDoc cdoc = (ClassDoc)doc;
213bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            doDocs(cdoc.fields());
214bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            doDocs(cdoc.constructors());
215bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            doDocs(cdoc.methods());
216bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            doDocs(cdoc.enumConstants());
217bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // don't call this to iterate over inner classes,
218bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // root.classes already includes them
219bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // doDocs(cdoc.innerClasses());
220bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
221bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
222bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        APIInfo info = createInfo(doc);
223bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (info != null) {
224bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            results.add(info);
225bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
226bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
227bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
228bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // Sigh. Javadoc doesn't indicate when the compiler generates
229bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // the values and valueOf enum methods.  The position of the
230bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // method for these is not always the same as the position of
231bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // the class, though it often is, so we can't use that.
232bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
233bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private boolean isIgnoredEnumMethod(ProgramElementDoc doc) {
234bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isMethod() && doc.containingClass().isEnum()) {
235bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // System.out.println("*** " + doc.qualifiedName() + " pos: " +
236bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            //                    doc.position().line() +
237bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            //                    " containined by: " +
238bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            //                    doc.containingClass().name() +
239bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            //                    " pos: " +
240bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            //                    doc.containingClass().position().line());
241bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // return doc.position().line() == doc.containingClass().position().line();
242bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
243bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            String name = doc.name();
244bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // assume we don't have enums that overload these method names.
245bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return "values".equals(name) || "valueOf".equals(name);
246bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
247bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return false;
248bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
249bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
250bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // isSynthesized also doesn't seem to work.  Let's do this, documenting
251bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // synthesized constructors for abstract classes is kind of weird.
252bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // We can't actually tell if the constructor was synthesized or is
253bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // actually in the docs, but this shouldn't matter.  We don't really
254bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // care if we didn't properly document the draft status of
255bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // default constructors for abstract classes.
256bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
257bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // Update: We mandate a no-arg synthetic constructor with explicit
258bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // javadoc comments by the policy. So, we no longer ignore abstract
259bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    // class's no-arg constructor blindly. -Yoshito 2014-05-21
260bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
261bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private boolean isAbstractClassDefaultConstructor(ProgramElementDoc doc) {
262bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return doc.isConstructor()
263bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            && doc.containingClass().isAbstract()
264bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            && "()".equals(((ConstructorDoc) doc).signature());
265bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
266bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
267bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final boolean IGNORE_NO_ARG_ABSTRACT_CTOR = false;
268bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
269bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private boolean ignore(ProgramElementDoc doc) {
270bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc == null) return true;
271bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isPrivate() || doc.isPackagePrivate()) return true;
272bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc instanceof MemberDoc && ((MemberDoc)doc).isSynthetic()) return true;
273bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.qualifiedName().indexOf(".misc") != -1) {
274bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            System.out.println("misc: " + doc.qualifiedName()); return true;
275bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
276bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (isIgnoredEnumMethod(doc)) {
277bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return true;
278bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
279bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
280bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (IGNORE_NO_ARG_ABSTRACT_CTOR && isAbstractClassDefaultConstructor(doc)) {
281bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            return true;
282bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
283bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
284bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (false && doc.qualifiedName().indexOf("LocaleDisplayNames") != -1) {
285bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          System.err.print("*** " + doc.qualifiedName() + ":");
286bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isClass()) System.err.print(" class");
287bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isConstructor()) System.err.print(" constructor");
288bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isEnum()) System.err.print(" enum");
289bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isEnumConstant()) System.err.print(" enum_constant");
290bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isError()) System.err.print(" error");
291bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isException()) System.err.print(" exception");
292bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isField()) System.err.print(" field");
293bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isInterface()) System.err.print(" interface");
294bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isMethod()) System.err.print(" method");
295bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          if (doc.isOrdinaryClass()) System.err.print(" ordinary_class");
296bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert          System.err.println();
297bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
298bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
299bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (!internal) { // debug
300bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            Tag[] tags = doc.tags();
301bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (int i = 0; i < tags.length; ++i) {
302bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (tagKindIndex(tags[i].kind()) == INTERNAL) { return true; }
303bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
304bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
305bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (pat != null && (doc.isClass() || doc.isInterface())) {
306bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (!pat.matcher(doc.name()).matches()) {
307bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return true;
308bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
309bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
310bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return false;
311bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
312bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
313bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static void writeResults(Collection c, BufferedWriter w) {
314bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        Iterator iter = c.iterator();
315bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        while (iter.hasNext()) {
316bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            APIInfo info = (APIInfo)iter.next();
317bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.writeln(w);
318bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
319bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
320bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
321bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private String trimBase(String arg) {
322bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (base != null) {
323bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (int n = arg.indexOf(base); n != -1; n = arg.indexOf(base, n)) {
324bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                arg = arg.substring(0, n) + arg.substring(n+base.length());
325bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
326bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
327bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return arg;
328bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
329bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
330bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    public APIInfo createInfo(ProgramElementDoc doc) {
331bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
332bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // Doc. name
333bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // Doc. isField, isMethod, isConstructor, isClass, isInterface
334bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ProgramElementDoc. containingClass, containingPackage
335bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ProgramElementDoc. isPublic, isProtected, isPrivate, isPackagePrivate
336bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ProgramElementDoc. isStatic, isFinal
337bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // MemberDoc.isSynthetic
338bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ExecutableMemberDoc isSynchronized, signature
339bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // Type.toString() // e.g. "String[][]"
340bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ClassDoc.isAbstract, superClass, interfaces, fields, methods, constructors, innerClasses
341bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // FieldDoc type
342bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // ConstructorDoc qualifiedName
343bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // MethodDoc isAbstract, returnType
344bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
345bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        APIInfo info = new APIInfo();
346bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (version) {
347bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.includeStatusVersion(true);
348bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
349bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
350bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // status
351bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String[] version = new String[1];
352bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        info.setType(APIInfo.STA, tagStatus(doc, version));
353bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        info.setStatusVersion(version[0]);
354bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
355bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // visibility
356bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isPublic()) {
357bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setPublic();
358bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isProtected()) {
359bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setProtected();
360bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isPrivate()) {
361bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setPrivate();
362bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else {
363bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // default is package
364bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
365bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
366bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // static
367bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isStatic()) {
368bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setStatic();
369bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else {
370bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // default is non-static
371bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
372bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
373bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // final
374bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isFinal() && !doc.isEnum()) {
375bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setFinal();
376bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else {
377bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // default is non-final
378bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
379bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
380bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        // type
381bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc.isField()) {
382bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setField();
383bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isMethod()) {
384bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setMethod();
385bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isConstructor()) {
386bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setConstructor();
387bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isClass() || doc.isInterface()) {
388bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (doc.isEnum()) {
389bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setEnum();
390bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else {
391bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setClass();
392bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
393bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc.isEnumConstant()) {
394bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setEnumConstant();
395bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
396bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
397bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        info.setPackage(trimBase(doc.containingPackage().name()));
3982d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3992d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        String className = (doc.isClass() || doc.isInterface() || (doc.containingClass() == null))
4002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                ? ""
4012d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                : doc.containingClass().name();
4022d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        info.setClassName(className);
4032d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
4042d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        String name = doc.name();
4052d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        if (doc.isConstructor()) {
4062d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            // Workaround for Javadoc incompatibility between 7 and 8.
4072d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            // Javadoc 7 prepends enclosing class name for a nested
4082d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            // class's constructor. We need to generate the same format
4092d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            // because existing ICU API signature were generated with
4102d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            // Javadoc 7 or older verions.
4112d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            int dotIdx = className.lastIndexOf('.');
4122d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            if (!name.contains(".") && dotIdx > 0) {
4132d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                name = className.substring(0, dotIdx + 1) + name;
4142d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            }
4152d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        }
4162d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        info.setName(name);
417bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
418bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (doc instanceof FieldDoc) {
419bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            FieldDoc fdoc = (FieldDoc)doc;
420bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setSignature(trimBase(fdoc.type().toString()));
421bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else if (doc instanceof ClassDoc) {
422bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ClassDoc cdoc = (ClassDoc)doc;
423bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
424bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (cdoc.isClass() && cdoc.isAbstract()) {
425bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                // interfaces are abstract by default, don't mark them as abstract
426bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setAbstract();
427bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
428bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
429bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            StringBuffer buf = new StringBuffer();
430bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (cdoc.isClass()) {
431bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                buf.append("extends ");
432bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                buf.append(cdoc.superclassType().toString());
433bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
434bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ClassDoc[] imp = cdoc.interfaces();
435bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (imp != null && imp.length > 0) {
436bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (buf.length() > 0) {
437bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    buf.append(" ");
438bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
439bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                buf.append("implements");
440bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                for (int i = 0; i < imp.length; ++i) {
441bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (i != 0) {
442bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        buf.append(",");
443bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
444bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    buf.append(" ");
445bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    buf.append(imp[i].qualifiedName());
446bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
447bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
448bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            info.setSignature(trimBase(buf.toString()));
449bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        } else {
450bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            ExecutableMemberDoc emdoc = (ExecutableMemberDoc)doc;
451bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (emdoc.isSynchronized()) {
452bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setSynchronized();
453bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
454bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
455bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (doc instanceof MethodDoc) {
456bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                MethodDoc mdoc = (MethodDoc)doc;
457bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (mdoc.isAbstract()) {
4582d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    // Workaround for Javadoc incompatibility between 7 and 8.
4592d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    // isAbstract() returns false for a method in an interface
4602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    // on Javadoc 7, while Javadoc 8 returns true. Because existing
4612d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    // API signature data files were generated before, we do not
4622d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    // set abstract if a method is in an interface.
4632d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    if (!mdoc.containingClass().isInterface()) {
4642d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                        info.setAbstract();
4652d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    }
466bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
467bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setSignature(trimBase(mdoc.returnType().toString() + emdoc.signature()));
468bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            } else {
469bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                // constructor
470bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                info.setSignature(trimBase(emdoc.signature()));
471bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
472bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
473bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
474bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return info;
475bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
476bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
477bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private int tagStatus(final ProgramElementDoc doc, String[] version) {
478bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        class Result {
479bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            boolean deprecatedFlag = false;
480bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int res = -1;
481bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            void set(int val) {
482bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (res != -1) {
483bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    boolean isValid = true;
484bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (val == APIInfo.STA_DEPRECATED) {
485bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // @internal and @obsolete should be always used along with @deprecated.
486bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // no change for status
487bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        isValid = (res == APIInfo.STA_INTERNAL || res == APIInfo.STA_OBSOLETE);
488bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        deprecatedFlag = true;
489bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    } else if (val == APIInfo.STA_INTERNAL) {
490bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // @deprecated should be always used along with @internal.
491bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // update status
492bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        if (res == APIInfo.STA_DEPRECATED) {
493bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                            res = val;  // APIInfo.STA_INTERNAL
494bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        } else {
495bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                            isValid = false;
496bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        }
497bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    } else if (val == APIInfo.STA_OBSOLETE) {
498bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // @deprecated should be always used along with @obsolete.
499bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // update status
500bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        if (res == APIInfo.STA_DEPRECATED) {
501bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                            res = val;  // APIInfo.STA_OBSOLETE
502bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        } else {
503bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                            isValid = false;
504bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        }
505bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    } else {
506bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // two different status tags must not co-exist, except for
507bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // following two cases:
508bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // 1. @internal and @deprecated
509bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        // 2. @obsolete and @deprecated
510bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        isValid = false;
511bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
512bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (!isValid) {
513bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        System.err.println("bad doc: " + doc + " both: "
514bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                                           + APIInfo.getTypeValName(APIInfo.STA, res) + " and: "
515bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                                           + APIInfo.getTypeValName(APIInfo.STA, val));
516bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        return;
517bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
518bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } else {
519bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    // ok to replace with new tag
520bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    res = val;
521bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (val == APIInfo.STA_DEPRECATED) {
522bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        deprecatedFlag = true;
523bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
524bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
525bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
526bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int get() {
527bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (res == -1) {
528bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    System.err.println("warning: no tag for " + doc);
529bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    return 0;
530bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } else if (res == APIInfo.STA_INTERNAL && !deprecatedFlag) {
531bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    System.err.println("warning: no @deprecated tag for @internal API: " + doc);
532bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
533bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return res;
534bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
535bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
536bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
537bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        Tag[] tags = doc.tags();
538bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        Result result = new Result();
539bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String statusVer = "";
540bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < tags.length; ++i) {
541bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            Tag tag = tags[i];
542bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
543bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            String kind = tag.kind();
544bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int ix = tagKindIndex(kind);
545bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
546bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            switch (ix) {
547bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case INTERNAL:
548bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(internal ? APIInfo.STA_INTERNAL : -2); // -2 for legacy compatibility
549bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
550bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
551bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
552bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case DRAFT:
553bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(APIInfo.STA_DRAFT);
554bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
555bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
556bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
557bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case STABLE:
558bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(APIInfo.STA_STABLE);
559bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
560bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
561bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
562bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case DEPRECATED:
563bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(APIInfo.STA_DEPRECATED);
564bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
565bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
566bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
567bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case OBSOLETE:
568bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                result.set(APIInfo.STA_OBSOLETE);
569bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                statusVer = getStatusVersion(tag);
570bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
571bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
572bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SINCE:
573bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case EXCEPTION:
574bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case VERSION:
575bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case UNKNOWN:
576bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case AUTHOR:
577bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SEE:
578bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case PARAM:
579bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case RETURN:
580bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case THROWS:
581bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            case SERIAL:
582bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                break;
583bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
584bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            default:
585bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                throw new RuntimeException("unknown index " + ix + " for tag: " + kind);
586bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
587bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
588bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
589bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (version != null) {
590bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            version[0] = statusVer;
591bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
592bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return result.get();
593bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
594bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
595bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private String getStatusVersion(Tag tag) {
596bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        String text = tag.text();
597bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        if (text != null && text.length() > 0) {
598bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            // Extract version string
599bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int start = -1;
600bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            int i = 0;
601bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            for (; i < text.length(); i++) {
602bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                char ch = text.charAt(i);
603bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                if (ch == '.' || (ch >= '0' && ch <= '9')) {
604bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    if (start == -1) {
605bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                        start = i;
606bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    }
607bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                } else if (start != -1) {
608bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                    break;
609bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                }
610bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
611bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (start != -1) {
612bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return text.substring(start, i);
613bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
614bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
615bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return "";
616bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
617bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
618bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int UNKNOWN = -1;
619bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int INTERNAL = 0;
620bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int DRAFT = 1;
621bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int STABLE = 2;
622bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int SINCE = 3;
623bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int DEPRECATED = 4;
624bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int AUTHOR = 5;
625bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int SEE = 6;
626bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int VERSION = 7;
627bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int PARAM = 8;
628bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int RETURN = 9;
629bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int THROWS = 10;
630bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int OBSOLETE = 11;
631bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int EXCEPTION = 12;
632bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static final int SERIAL = 13;
633bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
634bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    private static int tagKindIndex(String kind) {
635bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        final String[] tagKinds = {
636bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            "@internal", "@draft", "@stable", "@since", "@deprecated", "@author", "@see",
637bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            "@version", "@param", "@return", "@throws", "@obsolete", "@exception", "@serial"
638bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        };
639bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
640bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        for (int i = 0; i < tagKinds.length; ++i) {
641bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            if (kind.equals(tagKinds[i])) {
642bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert                return i;
643bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert            }
644bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        }
645bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        return UNKNOWN;
646bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert    }
647bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert}
648