KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > groboutils > codecoverage > v2 > report > XmlReportGenerator


1 /*
2  * @(#)XmlReportGenerator.java
3  *
4  * Copyright (C) 2002,2003 Matt Albrecht
5  * groboclown@users.sourceforge.net
6  * http://groboutils.sourceforge.net
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  */

26
27 package net.sourceforge.groboutils.codecoverage.v2.report;
28
29 import java.io.IOException JavaDoc;
30 import java.text.NumberFormat JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Map JavaDoc;
34
35 import javax.xml.parsers.DocumentBuilder JavaDoc;
36 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
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 JavaDoc;
46 import org.w3c.dom.Element JavaDoc;
47
48
49 /**
50  * Creates an XML formatted report, suitable for framing.
51  * <p>
52  * Re-written to use DOM for XML creation; see bug 847334.
53  *
54  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
55  * @version $Date: 2004/04/15 05:48:26 $
56  * @since December 18, 2002
57  * @see IAnalysisMetaData
58  */

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 JavaDoc DFORMAT = NumberFormat.getInstance();
66     private static final NumberFormat JavaDoc IFORMAT = NumberFormat.getInstance();
67     static {
68         DFORMAT.setMaximumFractionDigits( 2 );
69         DFORMAT.setMinimumFractionDigits( 2 );
70         IFORMAT.setMaximumFractionDigits( 0 );
71     }
72     
73     private DocumentBuilder JavaDoc 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     /**
130      * Sends the generated report to <tt>out</tt> using the given module
131      * and data set.
132      *
133      * @return the root element generated.
134      */

135     public Element JavaDoc createReport( IAnalysisModule module,
136             AnalysisModuleData data )
137             throws IOException JavaDoc
138     {
139         if (module == null || data == null)
140         {
141             throw new IllegalArgumentException JavaDoc("no null args");
142         }
143         
144         Document JavaDoc doc = this.docBuilder.newDocument();
145         
146         // get the list of all classes under consideration
147
final String JavaDoc classSigs[] = data.getClassSignatures();
148         Map JavaDoc packageCounts = loadPackageCounts( classSigs );
149         
150         Element JavaDoc rootEl = createRootNode( module, doc );
151         
152         // get each class's count, and append the output for each
153
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 JavaDoc iter = packageCounts.keySet().iterator();
166         while (iter.hasNext())
167         {
168             String JavaDoc pkgName = (String JavaDoc)iter.next();
169             CoverageCount pkgCount = (CoverageCount)packageCounts.get(
170                 pkgName );
171             writePackage( pkgName, pkgCount, rootEl, doc );
172             totalCount.add( pkgCount );
173         }
174         // don't need this memory anymore
175
packageCounts = null;
176         writeCoverage( totalCount, rootEl, doc );
177         
178         return rootEl;
179     }
180     
181     
182     
183     private Element JavaDoc createRootNode( IAnalysisModule module, Document JavaDoc doc )
184     {
185         if (module == null || doc == null)
186         {
187             throw new IllegalArgumentException JavaDoc("no null args");
188         }
189         
190         Element JavaDoc 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 JavaDoc rootEl, Document JavaDoc doc )
201     {
202         if (cr == null || cms == null || rootEl == null || doc == null)
203         {
204             throw new IllegalArgumentException JavaDoc("no null args");
205         }
206         
207         final String JavaDoc classSig = cr.getClassSignature();
208         final String JavaDoc className = cr.getClassName();
209         
210         Element JavaDoc 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 JavaDoc packageName, CoverageCount pkgCount,
226             Element JavaDoc parent, Document JavaDoc doc )
227     {
228         if (packageName == null || pkgCount == null || parent == null ||
229                 doc == null)
230         {
231             throw new IllegalArgumentException JavaDoc("no null args");
232         }
233         
234         Element JavaDoc 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 JavaDoc parent,
243             Document JavaDoc doc )
244     {
245         if (cms == null || parent == null || doc == null)
246         {
247             throw new IllegalArgumentException JavaDoc("no null args");
248         }
249         
250         final CoverageCount classCoverage = new CoverageCount();
251         final String JavaDoc methodList[] = cms.getMethodSignatures();
252         for (int i = 0; i < methodList.length; ++i)
253         {
254             String JavaDoc methodSig = methodList[i];
255             CoverageCount methodCoverage = new CoverageCount();
256             
257             Element JavaDoc 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             // covered marks
263
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             // uncovered marks
272
// (note that putting this allocation in the same array is a bit
273
// of a memory conservation)
274
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 JavaDoc parent, Document JavaDoc doc )
293     {
294         if (mr == null || parent == null || doc == null)
295         {
296             throw new IllegalArgumentException JavaDoc("no null args");
297         }
298         
299         final IAnalysisMetaData amd = mr.getAnalysisMetaData();
300         Element JavaDoc 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 JavaDoc parent,
314             Document JavaDoc doc )
315     {
316         if (cc == null || parent == null || doc == null)
317         {
318             throw new IllegalArgumentException JavaDoc("no null args");
319         }
320         Element JavaDoc 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     //-----------------------------------------------------------------------
336
// Helper / utilities
337

338     
339     private Map JavaDoc loadPackageCounts( String JavaDoc[] classSigs )
340     {
341         PackageSorter ps = new PackageSorter();
342         ps.addClassSignatures( classSigs );
343         String JavaDoc[] pkgs = ps.getPackages();
344         
345         Map JavaDoc counts = new HashMap JavaDoc();
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 JavaDoc getPackageName( String JavaDoc className )
355     {
356         return PackageSorter.getPackageName( className );
357     }
358     
359     
360     private String JavaDoc getClassName( String JavaDoc classSig )
361     {
362         return ClassSignatureUtil.getInstance().getClassName( classSig );
363     }
364     
365     
366     private String JavaDoc format( int i )
367     {
368         return IFORMAT.format( (long)i );
369     }
370     
371     
372     private String JavaDoc format( double d )
373     {
374         return DFORMAT.format( d );
375     }
376     
377     
378     private String JavaDoc formatNumber( int i )
379     {
380         return Integer.toString( i );
381     }
382     
383     
384     private String JavaDoc formatNumber( double d )
385     {
386         return Double.toString( d );
387     }
388     
389     
390     private static DocumentBuilder JavaDoc getDocumentBuilder()
391     {
392         try
393         {
394             return DocumentBuilderFactory.newInstance().newDocumentBuilder();
395         }
396         catch (Exception JavaDoc ex)
397         {
398             throw new ExceptionInInitializerError JavaDoc( ex );
399         }
400     }
401     
402     
403     static String JavaDoc translate( String JavaDoc methodSig )
404     {
405         if (methodSig == null)
406         {
407             return null;
408         }
409         
410         
411         // Translate both the method name and the method arguments
412
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 JavaDoc mname = methodSig.substring( 0, pos1 );
423         
424         // translate the method names - should this be done???
425
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 JavaDoc sig = new StringBuffer JavaDoc( mname );
436         sig.append( '(' );
437         String JavaDoc s = methodSig.substring( pos1, pos2+1 );
438         if (!"()".equals( s ))
439         {
440             String JavaDoc 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         // don't include return value
454
return new String JavaDoc( sig );
455     }
456 }
457
458
Popular Tags