1 23 24 package tests.org.enhydra.xml.xhtml.dominfo; 25 26 import java.io.PrintWriter ; 27 import java.util.HashSet ; 28 import java.util.Iterator ; 29 import java.util.Set ; 30 31 35 public class Report { 36 37 private static final int NUM_COLUMNS = 4; 38 39 40 private static final int TAG_COLUMN_IDX = 0; 41 private static final int HTML_INTER_COLUMN = 1; 42 private static final int XHTML_INTER_COLUMN = 2; 43 private static final int XHTML_IMPL_COLUMN = 3; 44 45 46 private static final int[] COLUMN_WIDTHS = { 47 12, 25, 25, 25 48 }; 49 50 51 private PrintWriter fOut; 52 53 54 private StringBuffer [] fColumns = new StringBuffer [NUM_COLUMNS]; 55 56 57 private String fDoubleLine; 58 private String fSingleLine; 59 60 61 private Relations fRelations; 62 63 64 private boolean fSkipCleanAttrRelations; 65 66 69 public Report(String dtdPath, 70 PrintWriter out, 71 boolean skipCleanAttrRelations) { 72 for (int col = 0; col < NUM_COLUMNS; col++) { 73 fColumns[col] = new StringBuffer (4096); 74 } 75 fRelations = new Relations(dtdPath); 76 fOut = out; 77 fDoubleLine = makeLine('='); 78 fSingleLine = makeLine('-'); 79 fSkipCleanAttrRelations = skipCleanAttrRelations; 80 } 81 82 85 private String makeLine(char ch) { 86 int len = 0; 87 for (int idx = 0; idx < COLUMN_WIDTHS.length; idx++) { 88 len += COLUMN_WIDTHS[idx]; 89 } 90 StringBuffer buf = new StringBuffer (len); 91 for (int cnt = 0; cnt < len; cnt++) { 92 buf.append(ch); 93 } 94 return buf.toString(); 95 } 96 97 98 private String unqualName(String name) { 99 int idx = name.lastIndexOf('.'); 100 if (idx < 0) { 101 return name; 102 } else { 103 return name.substring(idx+1); 104 } 105 } 106 107 108 private void print(int col, 109 String s) { 110 fColumns[col].append(s); 111 } 112 113 114 private void println(int col) { 115 fColumns[col].append('\n'); 116 } 117 118 119 private void println(int col, 120 String s) { 121 print(col, s); 122 println(col); 123 } 124 125 126 private void printSingleLine(int col) { 127 fColumns[col].append(fSingleLine.substring(0, COLUMN_WIDTHS[col])); 128 println(col); 129 } 130 131 132 private boolean allDone(int[] nextChar, 133 String [] columns) { 134 for (int col = 0; col < NUM_COLUMNS; col++) { 135 if (nextChar[col] < columns[col].length()) { 136 return false; 137 } 138 } 139 return true; 140 } 141 142 143 private int charsOnLine(String column, 144 int nextChar) { 145 if (nextChar >= column.length()) { 146 return 0; 147 } else { 148 int nlIdx = column.indexOf('\n', nextChar); 149 if (nlIdx < 0) { 150 return (column.length() - nextChar); 151 } else { 152 return (nlIdx - nextChar); 153 } 154 } 155 } 156 157 158 private int writeCol(String column, 159 int nextChar, 160 int width) { 161 int charCnt = charsOnLine(column, nextChar); 162 int writeCnt = (charCnt < width) ? charCnt : width; 163 if (writeCnt > 0) { 164 fOut.write(column, nextChar, writeCnt); 165 } 166 for (int cnt = charCnt; cnt < width; cnt++) { 167 fOut.write(' '); 168 } 169 return nextChar + charCnt + 1; 170 } 171 172 173 private void flush() { 174 int[] nextChar = new int[NUM_COLUMNS]; 175 String [] columns = new String [NUM_COLUMNS]; 176 for (int col = 0; col < NUM_COLUMNS; col++) { 177 columns[col] = fColumns[col].toString(); 178 fColumns[col].setLength(0); 179 } 180 while (!allDone(nextChar, columns)) { 182 for (int col = 0; col < NUM_COLUMNS; col++) { 184 nextChar[col] = writeCol(columns[col], nextChar[col], 185 COLUMN_WIDTHS[col]); 186 } 187 fOut.println(); 188 } 189 } 190 191 192 private void writeElementInfoName(Relations.TagRelation tagRel, 193 int col) { 194 DTDInfo.ElementInfo elementInfo = tagRel.getElementInfo(); 195 if (elementInfo != null) { 196 println(col, elementInfo.getRawName()); 197 } else { 198 println(col, tagRel.getTagName()); 199 } 200 } 201 202 203 private void writeElementInfoAttrs(DTDInfo.ElementInfo elementInfo, 204 int col) { 205 printSingleLine(col); 206 Iterator attrNames = elementInfo.getAttrNames().iterator(); 207 while (attrNames.hasNext()) { 208 println(col, (String )attrNames.next()); 209 } 210 } 211 212 213 private void writeElementClassName(DOMInfo.ElementClass elementClass, 214 int col) { 215 println(col, unqualName(elementClass.getName())); 216 } 217 218 219 private void writeElementClassImplements(DOMInfo.ElementClass elementClass, 220 int col) { 221 printSingleLine(col); 222 Iterator impls = elementClass.getImplementsNames().iterator(); 223 while (impls.hasNext()) { 224 String name = (String )impls.next(); 225 if (!(name.equals(org.w3c.dom.Node .class.getName()) 226 || name.equals(org.w3c.dom.Element .class.getName()))) { 227 println(col, unqualName(name)); 228 } 229 } 230 } 231 232 233 private void writeElementClassProps(DOMInfo.ElementClass elementClass, 234 int col) { 235 printSingleLine(col); 236 Iterator propNames = elementClass.getPropertyNames().iterator(); 237 while (propNames.hasNext()) { 238 DOMInfo.ElementProperty prop = elementClass.getProperty((String )propNames.next()); 239 println(col, prop.getName()); 240 } 241 } 242 243 246 private void writeAttrRelationProp(DOMInfo.ElementProperty elementPropertyInfo, 247 int col) { 248 if (elementPropertyInfo == null) { 249 println(col, "*"); 250 } else { 251 println(col, elementPropertyInfo.getName()); 252 } 253 } 254 255 256 private String getPropName(Relations.AttrRelation attrRel, 257 int domIdx) { 258 DOMInfo.ElementProperty elementPropertyInfo = attrRel.getElementPropertyInfo(domIdx); 259 if (elementPropertyInfo == null) { 260 return null; 261 } else { 262 return elementPropertyInfo.getName(); 263 } 264 } 265 266 269 private static Set fAttrIsClean = new HashSet (); 270 private static Set fXHTMLPropIsClean = new HashSet (); 271 static { 272 fAttrIsClean.add("onblur"); 273 fAttrIsClean.add("onclick"); 274 fAttrIsClean.add("ondblclick"); 275 fAttrIsClean.add("onfocus"); 276 fAttrIsClean.add("onkeydown"); 277 fAttrIsClean.add("onkeypress"); 278 fAttrIsClean.add("onkeyup"); 279 fAttrIsClean.add("onmousedown"); 280 fAttrIsClean.add("onmousemove"); 281 fAttrIsClean.add("onmouseout"); 282 fAttrIsClean.add("onmouseover"); 283 fAttrIsClean.add("onmouseup"); 284 fAttrIsClean.add("style"); 285 fAttrIsClean.add("xml:lang"); 286 fXHTMLPropIsClean.add("XmlLang"); 287 } 288 289 290 private boolean skipAttrRelation(Relations.AttrRelation attrRel, 291 boolean first) { 292 if (fSkipCleanAttrRelations) { 293 if ((attrRel.getNextAttrRelation() != null) || !first) { 294 return false; 296 } 297 String htmlName = getPropName(attrRel, Relations.HTML_INTERFACE_IDX); 299 String xhtmlIFaceName = getPropName(attrRel, Relations.XHTML_INTERFACE_IDX); 300 String xhtmlImplName = getPropName(attrRel, Relations.XHTML_IMPLEMENTATION_IDX); 301 302 303 if (fAttrIsClean.contains(attrRel.getAttrName()) 305 || ((xhtmlIFaceName != null) && fXHTMLPropIsClean.contains(xhtmlIFaceName)) 306 || ((xhtmlImplName != null) && fXHTMLPropIsClean.contains(xhtmlImplName))) { 307 return true; } 309 310 if (attrRel.getAttrInfo() == null) { 311 return false; 313 } 314 315 if ((htmlName != null) && htmlName.equals(xhtmlIFaceName) && htmlName.equals(xhtmlImplName)) { 316 return true; } 318 } 319 return false; 320 } 321 322 323 326 private void writeAttrRelation(Relations.AttrRelation attrRel, 327 boolean first) { 328 if (skipAttrRelation(attrRel, first)) { 329 return; 330 } 331 332 if (first) { 335 if (attrRel.getAttrInfo() != null) { 336 println(TAG_COLUMN_IDX, attrRel.getAttrName()); 337 } else { 338 println(TAG_COLUMN_IDX, "*"); 339 } 340 } 341 writeAttrRelationProp(attrRel.getElementPropertyInfo(Relations.HTML_INTERFACE_IDX), 342 HTML_INTER_COLUMN); 343 writeAttrRelationProp(attrRel.getElementPropertyInfo(Relations.XHTML_INTERFACE_IDX), 344 XHTML_INTER_COLUMN); 345 writeAttrRelationProp(attrRel.getElementPropertyInfo(Relations.XHTML_IMPLEMENTATION_IDX), 346 XHTML_IMPL_COLUMN); 347 } 348 349 352 private void writeAttrRelationChain(Relations.AttrRelation attrRel) { 353 boolean first = true; 354 while (attrRel != null) { 355 writeAttrRelation(attrRel, first); 356 first = false; 357 attrRel = attrRel.getNextAttrRelation(); 358 } 359 flush(); 360 } 361 362 365 private void writeAttrRelations(Relations.TagRelation tagRel) { 366 for (int col = 0; col < NUM_COLUMNS; col++) { 367 printSingleLine(col); 368 } 369 370 Iterator attrNames = tagRel.getAttrRelationNames().iterator(); 371 while (attrNames.hasNext()) { 372 writeAttrRelationChain(tagRel.getAttrRelation((String )attrNames.next())); 373 } 374 } 375 376 377 private void tagReport(Relations.TagRelation tagRel) { 378 fOut.println(fDoubleLine); 379 writeElementInfoName(tagRel, TAG_COLUMN_IDX); 380 writeElementClassName(tagRel.getElementClassInfo(Relations.HTML_INTERFACE_IDX), 381 HTML_INTER_COLUMN); 382 writeElementClassName(tagRel.getElementClassInfo(Relations.XHTML_INTERFACE_IDX), 383 XHTML_INTER_COLUMN); 384 writeElementClassName(tagRel.getElementClassInfo(Relations.XHTML_IMPLEMENTATION_IDX), 385 XHTML_IMPL_COLUMN); 386 flush(); 387 printSingleLine(TAG_COLUMN_IDX); 388 writeElementClassImplements(tagRel.getElementClassInfo(Relations.HTML_INTERFACE_IDX), 389 HTML_INTER_COLUMN); 390 writeElementClassImplements(tagRel.getElementClassInfo(Relations.XHTML_INTERFACE_IDX), 391 XHTML_INTER_COLUMN); 392 writeElementClassImplements(tagRel.getElementClassInfo(Relations.XHTML_IMPLEMENTATION_IDX), 393 XHTML_IMPL_COLUMN); 394 flush(); 395 writeAttrRelations(tagRel); 396 } 397 398 399 400 private void processUnusedElementClass(DOMInfo.ElementClass elementClass, 401 int col) { 402 fOut.println(fDoubleLine); 403 println(TAG_COLUMN_IDX, "*UNUSED*"); 404 writeElementClassName(elementClass, col); 405 writeElementClassImplements(elementClass, col); 406 writeElementClassProps(elementClass, col); 407 flush(); 408 } 409 410 411 private void unusedElementClassColumn(Set unusedElementClasses, 412 int col) { 413 Iterator elementClasses = unusedElementClasses.iterator(); 414 while (elementClasses.hasNext()) { 415 processUnusedElementClass((DOMInfo.ElementClass)elementClasses.next(), col); 416 } 417 } 418 419 420 private void unusedElementClassReport() { 421 unusedElementClassColumn(fRelations.getUnmappedElementClasses(Relations.HTML_INTERFACE_IDX), 422 HTML_INTER_COLUMN); 423 unusedElementClassColumn(fRelations.getUnmappedElementClasses(Relations.XHTML_INTERFACE_IDX), 424 XHTML_INTER_COLUMN); 425 unusedElementClassColumn(fRelations.getUnmappedElementClasses(Relations.XHTML_IMPLEMENTATION_IDX), 426 XHTML_IMPL_COLUMN); 427 } 428 429 430 public void report() { 431 fOut.println("DTD: " + fRelations.getDTDInfo().getDTDPath()); 432 Iterator tagNames = fRelations.getTagNames().iterator(); 433 while (tagNames.hasNext()) { 434 tagReport(fRelations.getTagRelation((String )tagNames.next())); 435 } 436 unusedElementClassReport(); 437 fOut.flush(); 438 } 439 440 443 public static void main(String [] args) { 444 int argIdx = 0; 445 boolean skipCleanAttrRelations = false; 446 while ((argIdx < args.length) && args[argIdx].startsWith("-")) { 447 if (args[argIdx].equals("-skip-clean-attr")) { 448 skipCleanAttrRelations = true; 449 } else { 450 System.err.println("bogus option: " + args[argIdx]); 451 } 452 argIdx++; 453 } 454 if ((args.length - argIdx) != 1) { 455 System.err.println("Wrong # args: Report [-skip-clean-attr] dtdfile"); 456 System.exit(1); 457 } 458 Report report = new Report(args[argIdx], new PrintWriter (System.out), 459 skipCleanAttrRelations); 460 report.report(); 461 } 462 } 463 | Popular Tags |