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