1 26 27 package net.sourceforge.groboutils.codecoverage.v2.report; 28 29 import java.io.IOException ; 30 import java.text.NumberFormat ; 31 import java.util.HashMap ; 32 import java.util.Iterator ; 33 import java.util.Map ; 34 35 import javax.xml.parsers.DocumentBuilder ; 36 import javax.xml.parsers.DocumentBuilderFactory ; 37 38 import net.sourceforge.groboutils.codecoverage.v2.IAnalysisMetaData; 39 import net.sourceforge.groboutils.codecoverage.v2.IAnalysisModule; 40 import net.sourceforge.groboutils.codecoverage.v2.datastore.ClassRecord; 41 import net.sourceforge.groboutils.codecoverage.v2.datastore.MarkRecord; 42 import net.sourceforge.groboutils.codecoverage.v2.util.ClassSignatureUtil; 43 44 import org.apache.bcel.classfile.Utility; 45 import org.w3c.dom.Document ; 46 import org.w3c.dom.Element ; 47 48 49 59 public class XmlReportGenerator implements IReportGenerator, IXmlReportConst 60 { 61 private static final org.apache.log4j.Logger LOG = 62 org.apache.log4j.Logger.getLogger( XmlReportGenerator.class ); 63 64 65 private static final NumberFormat DFORMAT = NumberFormat.getInstance(); 66 private static final NumberFormat IFORMAT = NumberFormat.getInstance(); 67 static { 68 DFORMAT.setMaximumFractionDigits( 2 ); 69 DFORMAT.setMinimumFractionDigits( 2 ); 70 IFORMAT.setMaximumFractionDigits( 0 ); 71 } 72 73 private DocumentBuilder docBuilder = getDocumentBuilder(); 74 75 private class CoverageCount 76 { 77 public CoverageCount() {} 78 public CoverageCount( boolean covered, byte weight ) 79 { 80 int cc = 0; 81 int tcc = 1; 82 if (covered) 83 { 84 cc = 1; 85 } 86 this.coveredCount = cc; 87 this.totalCount = tcc; 88 this.weightedCoverage = 89 ((double)weight + (double)Byte.MAX_VALUE + 1.0) 90 * (double)(cc + 1) / (double)Byte.MAX_VALUE * 2.0; 91 } 92 93 public int coveredCount; 94 public int totalCount; 95 public double weightedCoverage; 96 97 public void add( CoverageCount b ) 98 { 99 this.coveredCount += b.coveredCount; 100 this.totalCount += b.totalCount; 101 102 this.weightedCoverage += b.weightedCoverage; 103 } 104 105 106 public double getCoveredPercent() 107 { 108 if (this.totalCount == 0) 109 { 110 return 100.0; 111 } 112 return ((double)this.coveredCount / (double)this.totalCount) * 113 100.0; 114 } 115 116 117 public double getWeightedValue() 118 { 119 if (this.totalCount == 0) 120 { 121 return 100.0; 122 } 123 return (this.weightedCoverage / (double)this.totalCount) * 100.0; 124 } 125 } 126 127 128 129 135 public Element createReport( IAnalysisModule module, 136 AnalysisModuleData data ) 137 throws IOException 138 { 139 if (module == null || data == null) 140 { 141 throw new IllegalArgumentException ("no null args"); 142 } 143 144 Document doc = this.docBuilder.newDocument(); 145 146 final String classSigs[] = data.getClassSignatures(); 148 Map packageCounts = loadPackageCounts( classSigs ); 149 150 Element rootEl = createRootNode( module, doc ); 151 152 for (int i = 0; i < classSigs.length; ++i) 154 { 155 LOG.info( "Reading class "+classSigs[i]+"." ); 156 ClassMarkSet cms = data.createClassMarkSet( classSigs[i] ); 157 CoverageCount classCount = writeClass( cms, 158 data.getClassRecord( classSigs[i] ), rootEl, doc ); 159 CoverageCount pkgCount = (CoverageCount)packageCounts.get( 160 getPackageName( classSigs[i] ) ); 161 pkgCount.add( classCount ); 162 } 163 164 final CoverageCount totalCount = new CoverageCount(); 165 Iterator iter = packageCounts.keySet().iterator(); 166 while (iter.hasNext()) 167 { 168 String pkgName = (String )iter.next(); 169 CoverageCount pkgCount = (CoverageCount)packageCounts.get( 170 pkgName ); 171 writePackage( pkgName, pkgCount, rootEl, doc ); 172 totalCount.add( pkgCount ); 173 } 174 packageCounts = null; 176 writeCoverage( totalCount, rootEl, doc ); 177 178 return rootEl; 179 } 180 181 182 183 private Element createRootNode( IAnalysisModule module, Document doc ) 184 { 185 if (module == null || doc == null) 186 { 187 throw new IllegalArgumentException ("no null args"); 188 } 189 190 Element rootEl = doc.createElement( T_COVERAGEREPORT ); 191 doc.appendChild( rootEl ); 192 rootEl.setAttribute( A_MEASURE, module.getMeasureName() ); 193 rootEl.setAttribute( A_UNIT, module.getMeasureUnit() ); 194 195 return rootEl; 196 } 197 198 199 private CoverageCount writeClass( ClassMarkSet cms, ClassRecord cr, 200 Element rootEl, Document doc ) 201 { 202 if (cr == null || cms == null || rootEl == null || doc == null) 203 { 204 throw new IllegalArgumentException ("no null args"); 205 } 206 207 final String classSig = cr.getClassSignature(); 208 final String className = cr.getClassName(); 209 210 Element classEl = doc.createElement( T_CLASSCOVERAGE ); 211 rootEl.appendChild( classEl ); 212 classEl.setAttribute( A_CLASSSIGNATURE, classSig ); 213 classEl.setAttribute( A_CLASSNAME, className ); 214 classEl.setAttribute( A_PACKAGE, getPackageName( classSig ) ); 215 classEl.setAttribute( A_SOURCEFILE, cr.getSourceFileName() ); 216 217 final CoverageCount classCoverage = writeMethods( cms, classEl, doc ); 218 219 writeCoverage( classCoverage, classEl, doc ); 220 221 return classCoverage; 222 } 223 224 225 private void writePackage( String packageName, CoverageCount pkgCount, 226 Element parent, Document doc ) 227 { 228 if (packageName == null || pkgCount == null || parent == null || 229 doc == null) 230 { 231 throw new IllegalArgumentException ("no null args"); 232 } 233 234 Element packEl = doc.createElement( T_PACKAGE ); 235 parent.appendChild( packEl ); 236 packEl.setAttribute( A_NAME, packageName ); 237 238 writeCoverage( pkgCount, packEl, doc ); 239 } 240 241 242 private CoverageCount writeMethods( ClassMarkSet cms, Element parent, 243 Document doc ) 244 { 245 if (cms == null || parent == null || doc == null) 246 { 247 throw new IllegalArgumentException ("no null args"); 248 } 249 250 final CoverageCount classCoverage = new CoverageCount(); 251 final String methodList[] = cms.getMethodSignatures(); 252 for (int i = 0; i < methodList.length; ++i) 253 { 254 String methodSig = methodList[i]; 255 CoverageCount methodCoverage = new CoverageCount(); 256 257 Element methEl = doc.createElement( T_METHODCOVERAGE ); 258 parent.appendChild( methEl ); 259 methEl.setAttribute( A_METHODSIGNATURE, translate( methodSig ) ); 260 methEl.setAttribute( A_METHODSIGNATURE_REAL, methodSig ); 261 262 MarkRecord marks[] = cms.getCoveredMarksForMethod( methodSig ); 264 for (int markI = 0; markI < marks.length; ++markI) 265 { 266 CoverageCount cc = writeMark( marks[ markI ], true, 267 methEl, doc ); 268 methodCoverage.add( cc ); 269 } 270 271 marks = cms.getNotCoveredMarksForMethod( methodSig ); 275 for (int markI = 0; markI < marks.length; ++markI) 276 { 277 CoverageCount cc = writeMark( marks[ markI ], false, 278 methEl, doc ); 279 methodCoverage.add( cc ); 280 } 281 282 writeCoverage( methodCoverage, methEl, doc ); 283 284 classCoverage.add( methodCoverage ); 285 } 286 287 return classCoverage; 288 } 289 290 291 private CoverageCount writeMark( MarkRecord mr, boolean covered, 292 Element parent, Document doc ) 293 { 294 if (mr == null || parent == null || doc == null) 295 { 296 throw new IllegalArgumentException ("no null args"); 297 } 298 299 final IAnalysisMetaData amd = mr.getAnalysisMetaData(); 300 Element markEl = doc.createElement( T_MARK ); 301 parent.appendChild( markEl ); 302 markEl.setAttribute( A_COVERED, covered ? "true" : "false" ); 303 markEl.setAttribute( A_TEXT, amd.getCoveredFormattedText() ); 304 markEl.setAttribute( A_WEIGHT, formatNumber( amd.getInstructionWeight() ) ); 305 markEl.setAttribute( A_SOURCELINE, formatNumber( mr.getLineNumber() ) ); 306 307 CoverageCount cc = new CoverageCount( covered, 308 amd.getInstructionWeight() ); 309 return cc; 310 } 311 312 313 private void writeCoverage( CoverageCount cc, Element parent, 314 Document doc ) 315 { 316 if (cc == null || parent == null || doc == null) 317 { 318 throw new IllegalArgumentException ("no null args"); 319 } 320 Element cover = doc.createElement( T_COVER ); 321 parent.appendChild( cover ); 322 323 cover.setAttribute( A_COVERED_DISP, format( cc.coveredCount ) ); 324 cover.setAttribute( A_COVERED, formatNumber( cc.coveredCount ) ); 325 cover.setAttribute( A_TOTAL_DISP, format( cc.totalCount ) ); 326 cover.setAttribute( A_TOTAL, formatNumber( cc.totalCount ) ); 327 cover.setAttribute( A_PERCENTCOVERED_DISP, format( cc.getCoveredPercent() ) ); 328 cover.setAttribute( A_PERCENTCOVERED, formatNumber( cc.getCoveredPercent() ) ); 329 cover.setAttribute( A_WEIGHTEDPERCENT_DISP, format( cc.getWeightedValue() ) ); 330 cover.setAttribute( A_WEIGHTEDPERCENT, formatNumber( cc.getWeightedValue() ) ); 331 } 332 333 334 335 338 339 private Map loadPackageCounts( String [] classSigs ) 340 { 341 PackageSorter ps = new PackageSorter(); 342 ps.addClassSignatures( classSigs ); 343 String [] pkgs = ps.getPackages(); 344 345 Map counts = new HashMap (); 346 for (int i = 0; i < pkgs.length; ++i) 347 { 348 counts.put( pkgs[i], new CoverageCount() ); 349 } 350 return counts; 351 } 352 353 354 private String getPackageName( String className ) 355 { 356 return PackageSorter.getPackageName( className ); 357 } 358 359 360 private String getClassName( String classSig ) 361 { 362 return ClassSignatureUtil.getInstance().getClassName( classSig ); 363 } 364 365 366 private String format( int i ) 367 { 368 return IFORMAT.format( (long)i ); 369 } 370 371 372 private String format( double d ) 373 { 374 return DFORMAT.format( d ); 375 } 376 377 378 private String formatNumber( int i ) 379 { 380 return Integer.toString( i ); 381 } 382 383 384 private String formatNumber( double d ) 385 { 386 return Double.toString( d ); 387 } 388 389 390 private static DocumentBuilder getDocumentBuilder() 391 { 392 try 393 { 394 return DocumentBuilderFactory.newInstance().newDocumentBuilder(); 395 } 396 catch (Exception ex) 397 { 398 throw new ExceptionInInitializerError ( ex ); 399 } 400 } 401 402 403 static String translate( String methodSig ) 404 { 405 if (methodSig == null) 406 { 407 return null; 408 } 409 410 411 int pos1 = methodSig.indexOf( '(' ); 413 if (pos1 < 0) 414 { 415 return methodSig; 416 } 417 int pos2 = methodSig.indexOf( ')' ); 418 if (pos2 < 0) 419 { 420 return methodSig; 421 } 422 String mname = methodSig.substring( 0, pos1 ); 423 424 if ("<init>".equals( mname )) 426 { 427 mname = "[constructor]"; 428 } 429 else 430 if ("<clinit>".equals( mname )) 431 { 432 return "[static initializer]"; 433 } 434 435 StringBuffer sig = new StringBuffer ( mname ); 436 sig.append( '(' ); 437 String s = methodSig.substring( pos1, pos2+1 ); 438 if (!"()".equals( s )) 439 { 440 String parms[] = Utility.methodSignatureArgumentTypes( s ); 441 if (parms.length > 0) 442 { 443 sig.append( parms[0] ); 444 for (int i = 1; i < parms.length; ++i) 445 { 446 sig.append( ", " ); 447 sig.append( parms[i] ); 448 } 449 } 450 } 451 sig.append( ')' ); 452 453 return new String ( sig ); 455 } 456 } 457 458 | Popular Tags |