1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2010-2013, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9 package com.ibm.icu.dev.tool.docs; 10 11 import java.io.BufferedWriter; 12 import java.io.FileOutputStream; 13 import java.io.IOException; 14 import java.io.OutputStreamWriter; 15 import java.io.PrintWriter; 16 import java.util.BitSet; 17 import java.util.Date; 18 import java.util.TreeSet; 19 20 21 /** 22 * @author yumaoka 23 * 24 */ 25 public class CollectAPI { 26 private static final int MAXSTATE = APIInfo.STA_INTERNAL; 27 28 private APIData _apidata; 29 30 CollectAPI(String file)31 CollectAPI(String file) { 32 _apidata = APIData.read(file, true); 33 } 34 writeHTML(String outfile, BitSet filter)35 void writeHTML(String outfile, BitSet filter) throws IOException { 36 37 // collecting versions 38 TreeSet<String> versions = new TreeSet<String>(); 39 for (APIInfo info : _apidata.set) { 40 versions.add(info.getStatusVersion()); 41 } 42 43 FileOutputStream fos = new FileOutputStream(outfile); 44 PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"))); 45 46 String title = "ICU4J API Collection: " + _apidata.name; 47 String note = "Contents generated by CollectAPI tool on " + new Date().toString(); 48 49 pw.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); 50 pw.println("<html>"); 51 pw.println("<head>"); 52 pw.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"); 53 pw.println("<title>" + title + "</title>"); 54 pw.println("</head>"); 55 pw.println("<body>"); 56 57 pw.println("<h1>" + title + "</h1>"); 58 59 for (String ver : versions) { 60 boolean sawEntryForVersion = false; 61 62 for (int state = 0; state <= MAXSTATE; state++) { 63 if (!filter.get(state)) { 64 continue; 65 } 66 67 boolean firstInState = true; 68 String pack = ""; 69 String clas = "***"; // hack - we just need a class name never used 70 boolean inList = false; 71 72 for (APIInfo info : _apidata.set) { 73 if (!info.getStatusVersion().equals(ver)) { 74 continue; 75 } 76 if (state != info.getVal(APIInfo.STA)) { 77 continue; 78 } 79 80 if (!sawEntryForVersion) { 81 pw.println("<h2>Status Version: " + ver + "</h2>"); 82 sawEntryForVersion = true; 83 } 84 85 if (firstInState) { 86 pw.println("<h3>[" + getStatusTypeName(state) + "]</h3>"); 87 firstInState = false; 88 } 89 90 String packageName = info.getPackageName(); 91 if (!packageName.equals(pack)) { 92 if (inList) { 93 pw.println("</ul>"); 94 inList = false; 95 } 96 pw.println("<h4>Package: " + packageName + "</h4>"); 97 pack = packageName; 98 } 99 100 String className = info.getClassName(); 101 if (className.length() == 0) { 102 // next class 103 if (inList) { 104 pw.println("</ul>"); 105 inList = false; 106 } 107 pw.print("<p><span style='color:red'>Class: </span>"); 108 info.print(pw, false, true, false); 109 pw.println("</p>"); 110 clas = className; 111 continue; 112 } 113 if (!className.equals(clas)) { 114 if (inList) { 115 pw.println("</ul>"); 116 inList = false; 117 } 118 pw.println("<span style='color:green'>APIs: </span>" + className); 119 clas = className; 120 } 121 122 if (!inList) { 123 pw.println("<ul>"); 124 inList = true; 125 } 126 pw.print("<li>"); 127 info.print(pw, false, true, false); 128 pw.println("</li>"); 129 } 130 131 if (inList) { 132 pw.println("</ul>"); 133 } 134 } 135 136 if (sawEntryForVersion) { 137 pw.println(); 138 pw.println("<hr/>"); 139 } 140 } 141 142 pw.println("<p><i><font size=\"-1\">" + note + "</font></i></p>"); 143 144 pw.println("</body>"); 145 pw.println("</html>"); 146 pw.close(); 147 } 148 writeTSV(String outfile, BitSet filter)149 void writeTSV(String outfile, BitSet filter) throws IOException { 150 FileOutputStream fos = new FileOutputStream(outfile); 151 PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"))); 152 153 for (APIInfo info : _apidata.set) { 154 if (!filter.get(info.getVal(APIInfo.STA))) { 155 continue; 156 } 157 StringBuilder buf = new StringBuilder(); 158 159 // package 160 buf.append(info.getPackageName()); 161 buf.append("\t"); 162 163 // class 164 String className = info.getClassName(); 165 if (className.length() == 0) { 166 className = info.getName(); 167 } 168 buf.append(className); 169 buf.append("\t"); 170 171 // signature, etc 172 info.format(buf, false, false, false); 173 buf.append("\t"); 174 175 // status 176 buf.append(APIInfo.getTypeValName(APIInfo.STA, info.getVal(APIInfo.STA))); 177 buf.append("\t"); 178 179 // version 180 String statusVer = info.getStatusVersion(); 181 if (statusVer.length() == 0) { 182 statusVer = "[N/A]"; 183 } 184 buf.append(statusVer); 185 186 pw.println(buf.toString()); 187 } 188 pw.close(); 189 } 190 main(String[] args)191 public static void main(String[] args) { 192 String apifile = null; 193 String outfile = null; 194 BitSet filter = new BitSet(MAXSTATE + 1); 195 boolean isTSV = false; 196 197 // default filter 198 filter.set(APIInfo.STA_STABLE); 199 filter.set(APIInfo.STA_DRAFT); 200 filter.set(APIInfo.STA_DEPRECATED); 201 202 for (int i = 0; i < args.length; i++) { 203 if (args[i].equals("-f")) { 204 if (i + 1 == args.length) { 205 System.out.println("Missing filter argument"); 206 return; 207 } 208 i++; 209 String[] types = args[i].split(","); 210 filter.clear(); 211 for (String type : types) { 212 if (type.equalsIgnoreCase(getStatusTypeName(APIInfo.STA_STABLE))) { 213 filter.set(APIInfo.STA_STABLE); 214 } else if (type.equalsIgnoreCase(getStatusTypeName(APIInfo.STA_DRAFT))) { 215 filter.set(APIInfo.STA_DRAFT); 216 } else if (type.equalsIgnoreCase(getStatusTypeName(APIInfo.STA_DEPRECATED))) { 217 filter.set(APIInfo.STA_DEPRECATED); 218 } else if (type.equalsIgnoreCase(getStatusTypeName(APIInfo.STA_OBSOLETE))) { 219 filter.set(APIInfo.STA_OBSOLETE); 220 } else if (type.equalsIgnoreCase(getStatusTypeName(APIInfo.STA_INTERNAL))) { 221 filter.set(APIInfo.STA_INTERNAL); 222 } else { 223 System.out.println("Bad filter type " + type); 224 return; 225 } 226 } 227 } else if (args[i].equals("-o")) { 228 if (i + 1 == args.length) { 229 System.out.println("Missing filter argument"); 230 return; 231 } 232 i++; 233 outfile = args[i]; 234 } else if (args[i].equals("-t")) { 235 isTSV = true; 236 } else { 237 apifile = args[i]; 238 if (i + 1 != args.length) { 239 System.out.println("Too many arguments"); 240 return; 241 } 242 } 243 } 244 245 if (apifile == null) { 246 System.out.println("No API file specified"); 247 return; 248 } 249 250 CollectAPI collection = new CollectAPI(apifile); 251 252 try { 253 if (isTSV) { 254 if (outfile == null) { 255 outfile = "api.tsv"; 256 } 257 collection.writeTSV(outfile, filter); 258 } else { 259 if (outfile == null) { 260 outfile = "api.html"; 261 } 262 collection.writeHTML(outfile, filter); 263 } 264 } catch (IOException e) { 265 e.printStackTrace(); 266 } 267 } 268 getStatusTypeName(int status)269 private static String getStatusTypeName(int status) { 270 String name = null; 271 switch (status) { 272 case APIInfo.STA_STABLE: 273 name = "Stable"; 274 break; 275 276 case APIInfo.STA_DRAFT: 277 name = "Draft"; 278 break; 279 280 case APIInfo.STA_DEPRECATED: 281 name = "Deprecated"; 282 break; 283 284 case APIInfo.STA_OBSOLETE: 285 name = "Obsolete"; 286 break; 287 288 case APIInfo.STA_INTERNAL: 289 name = "Internal"; 290 break; 291 292 default: 293 throw new IllegalArgumentException("Bad API status type " + status); 294 } 295 296 return name; 297 } 298 } 299