KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)XmlCombinedReportGenerator.java
3  *
4  * Copyright (C) 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.LinkedList JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36
37 import javax.xml.parsers.DocumentBuilder JavaDoc;
38 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
39
40 import net.sourceforge.groboutils.codecoverage.v2.IAnalysisMetaData;
41
42 import org.w3c.dom.Document JavaDoc;
43 import org.w3c.dom.Element JavaDoc;
44 import org.w3c.dom.NodeList JavaDoc;
45
46
47 /**
48  * Combines all the XML Reports into a single XML report.
49  *
50  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
51  * @version $Date: 2004/04/15 05:48:26 $
52  * @since December 18, 2002
53  * @see IAnalysisMetaData
54  */

55 public class XmlCombinedReportGenerator implements IXmlCombinedReportConst
56 {
57     private static final org.apache.log4j.Logger LOG =
58         org.apache.log4j.Logger.getLogger( XmlCombinedReportGenerator.class );
59     
60     
61     private static final NumberFormat JavaDoc DFORMAT = NumberFormat.getInstance();
62     private static final NumberFormat JavaDoc IFORMAT = NumberFormat.getInstance();
63     static {
64         DFORMAT.setMaximumFractionDigits( 2 );
65         DFORMAT.setMinimumFractionDigits( 2 );
66         IFORMAT.setMaximumFractionDigits( 0 );
67     }
68     
69     private DocumentBuilder JavaDoc docBuilder = getDocumentBuilder();
70     
71     
72     private static class Report
73     {
74         String JavaDoc measureName;
75         String JavaDoc unitName;
76         Element JavaDoc current;
77         
78         public Report( Document JavaDoc doc )
79         {
80             Element JavaDoc e = doc.getDocumentElement();
81             if (!T_COVERAGEREPORT.equals( e.getTagName() ))
82             {
83                 throw new IllegalArgumentException JavaDoc( "Document root is not "+
84                     T_COVERAGEREPORT );
85             }
86             this.measureName = e.getAttribute( A_MEASURE );
87             this.unitName = e.getAttribute( A_UNIT );
88             if (this.measureName == null || this.measureName.length() <= 0
89                 || this.unitName == null || this.unitName.length() <= 0)
90             {
91                 throw new IllegalArgumentException JavaDoc(
92                     "Document root is not a proper "+T_COVERAGEREPORT );
93             }
94             this.current = e;
95         }
96         
97         public Report( String JavaDoc mn, String JavaDoc un, Element JavaDoc c )
98         {
99             this.measureName = mn;
100             this.unitName = un;
101             this.current = c;
102         }
103         
104         public Report getFirst( String JavaDoc childName )
105         {
106             NodeList JavaDoc list = this.current.getChildNodes();
107             for (int i = 0; i < list.getLength(); ++i)
108             {
109                 if (list.item(i) instanceof Element JavaDoc)
110                 {
111                     Element JavaDoc e = (Element JavaDoc)list.item(i);
112                     if (e.getTagName().equals( childName ))
113                     {
114                         return new Report( this.measureName, this.unitName, e );
115                     }
116                 }
117             }
118             return null;
119         }
120         
121         public Report[] getAll( String JavaDoc childName )
122         {
123             NodeList JavaDoc list = this.current.getChildNodes();
124             List JavaDoc out = new LinkedList JavaDoc();
125             for (int i = list.getLength(); --i >= 0;)
126             {
127                 if (list.item(i) instanceof Element JavaDoc)
128                 {
129                     Element JavaDoc e = (Element JavaDoc)list.item(i);
130                     if (e.getTagName().equals( childName ))
131                     {
132                         out.add( new Report( this.measureName, this.unitName,
133                             e ) );
134                     }
135                 }
136             }
137             Report r[] = (Report[])out.toArray( new Report[ out.size() ] );
138             return r;
139         }
140     }
141     
142     
143     /**
144      * Contains all reports at the same element depth
145      */

146     private static class ReportSet
147     {
148         private Map JavaDoc reports = new HashMap JavaDoc();
149         
150         public ReportSet( Document JavaDoc docs[] )
151         {
152             for (int i = 0; i < docs.length; ++i)
153             {
154                 Report r = new Report( docs[i] );
155                 this.reports.put( r.measureName, r );
156             }
157         }
158         
159         public ReportSet( Report r[] )
160         {
161             for (int i = 0; i < r.length; ++i)
162             {
163                 this.reports.put( r[i].measureName, r[i] );
164             }
165         }
166         
167         public ReportSet getFirst( String JavaDoc childName )
168         {
169             Iterator JavaDoc iter = getMeasureNames();
170             List JavaDoc reps = new LinkedList JavaDoc();
171             while (iter.hasNext())
172             {
173                 Report r = getReport( (String JavaDoc)iter.next() );
174                 if (r != null)
175                 {
176                     r = r.getFirst( childName );
177                     if (r != null)
178                     {
179                         reps.add( r );
180                     }
181                 }
182             }
183             return new ReportSet( (Report[])reps.toArray(
184                 new Report[ reps.size() ] ) );
185         }
186         
187         public Report getReport( String JavaDoc measureName )
188         {
189             Object JavaDoc o = this.reports.get( measureName );
190             if (!(o instanceof Report))
191             {
192                 throw new IllegalStateException JavaDoc("Expected Report, but found "
193                     +o+" ("+o.getClass()+")" );
194             }
195             Report r = (Report)o;
196             //Report r = (Report)this.reports.get( measureName );
197
/* there might be an empty measure for this sub-element.
198             if (r == null)
199             {
200                 throw new IllegalArgumentException(
201                     "Unknown measure name "+measureName );
202             }
203             */

204             return r;
205         }
206         
207         // helper method.
208
public Report nextReport( Iterator JavaDoc iter )
209         {
210             return getReport( (String JavaDoc)iter.next() );
211         }
212         
213         public Iterator JavaDoc getMeasureNames()
214         {
215             return this.reports.keySet().iterator();
216         }
217     }
218     
219     
220     /**
221      * Create a report from the given report set.
222      *
223      * @return the root element generated.
224      */

225     public Element JavaDoc createReport( Document JavaDoc reports[] )
226             throws IOException JavaDoc
227     {
228         if (reports == null)
229         {
230             throw new IllegalArgumentException JavaDoc("no null args");
231         }
232         
233         Document JavaDoc doc = this.docBuilder.newDocument();
234         Element JavaDoc rootEl = createRootNode( doc );
235         
236         ReportSet rootDocs = new ReportSet( reports );
237         join( doc, rootEl, rootDocs );
238         
239         return rootEl;
240     }
241     
242     
243     private Element JavaDoc createRootNode( Document JavaDoc doc )
244     {
245         if (doc == null)
246         {
247             throw new IllegalArgumentException JavaDoc("no null args");
248         }
249         
250         Element JavaDoc rootEl = doc.createElement( T_COVERAGEREPORT );
251         doc.appendChild( rootEl );
252         
253         return rootEl;
254     }
255     
256     
257     private void join( Document JavaDoc doc, Element JavaDoc rootEl, ReportSet reports )
258     {
259         // make a top-level node that describes all the measure types
260
Element JavaDoc moduleTypesEl = doc.createElement( T_MODULETYPES );
261         rootEl.appendChild( moduleTypesEl );
262         Iterator JavaDoc iter = reports.getMeasureNames();
263         while (iter.hasNext())
264         {
265             Report r = reports.nextReport( iter );
266             Element JavaDoc moduleEl = doc.createElement( T_MODULE );
267             moduleTypesEl.appendChild( moduleEl );
268             moduleEl.setAttribute( A_MEASURE, r.measureName );
269             moduleEl.setAttribute( A_UNIT, r.unitName );
270         }
271         
272         // join the total coverage numbers
273
joinCoverage( doc, rootEl, reports.getFirst( T_COVER ) );
274         
275         // join the package coverage numbers
276
ReportSet[] byPackage = sort( reports, T_PACKAGE, A_NAME );
277         for (int i = 0; i < byPackage.length; ++i)
278         {
279             joinPackage( doc, rootEl, byPackage[i] );
280         }
281         
282         // join the class coverage numbers
283
ReportSet[] byClass = sort( reports, T_CLASSCOVERAGE, A_CLASSSIGNATURE );
284         for (int i = 0; i < byClass.length; ++i)
285         {
286             joinClass( doc, rootEl, byClass[i] );
287         }
288     }
289     
290     
291     private void joinClass( Document JavaDoc doc, Element JavaDoc parentEl, ReportSet reports )
292     {
293         Iterator JavaDoc iter = reports.getMeasureNames();
294         if (!iter.hasNext())
295         {
296             throw new IllegalStateException JavaDoc("No class elements.");
297         }
298         Element JavaDoc classEl = doc.createElement( T_CLASSCOVERAGE );
299         parentEl.appendChild( classEl );
300         
301         // join the coverage numbers
302
joinCoverage( doc, classEl, reports.getFirst( T_COVER ) );
303         
304         Report r = reports.nextReport( iter );
305         iter = null;
306         classEl.setAttribute( A_CLASSSIGNATURE, r.current.getAttribute( A_CLASSSIGNATURE ) );
307         classEl.setAttribute( A_CLASSNAME, r.current.getAttribute( A_CLASSNAME ) );
308         classEl.setAttribute( A_PACKAGE, r.current.getAttribute( A_PACKAGE ) );
309         classEl.setAttribute( A_SOURCEFILE, r.current.getAttribute( A_SOURCEFILE ) );
310         r = null;
311         
312         
313         // join the method coverage numbers
314
ReportSet[] byMethod = sort( reports, T_METHODCOVERAGE, A_METHODSIGNATURE );
315         for (int i = 0; i < byMethod.length; ++i)
316         {
317             joinMethod( doc, classEl, byMethod[i] );
318         }
319     }
320     
321     
322     private void joinMethod( Document JavaDoc doc, Element JavaDoc parentEl, ReportSet reports )
323     {
324         Iterator JavaDoc iter = reports.getMeasureNames();
325         if (!iter.hasNext())
326         {
327             throw new IllegalStateException JavaDoc("No class elements.");
328         }
329         
330         Element JavaDoc methodEl = doc.createElement( T_METHODCOVERAGE );
331         parentEl.appendChild( methodEl );
332         boolean notSetup = true;
333         while (iter.hasNext())
334         {
335             Report r = reports.nextReport( iter );
336             if (notSetup)
337             {
338                 methodEl.setAttribute( A_METHODSIGNATURE, r.current.getAttribute( A_METHODSIGNATURE ) );
339                 methodEl.setAttribute( A_METHODSIGNATURE_REAL, r.current.getAttribute( A_METHODSIGNATURE_REAL ) );
340                 notSetup = false;
341             }
342             Report marks[] = r.getAll( T_MARK );
343             for (int i = 0; i < marks.length; ++i)
344             {
345                 joinMark( doc, methodEl, marks[i] );
346             }
347         }
348         
349         // join the coverage numbers
350
joinCoverage( doc, methodEl, reports.getFirst( T_COVER ) );
351     }
352     
353     
354     private void joinMark( Document JavaDoc doc, Element JavaDoc parentEl, Report mark )
355     {
356         // original
357
// <mark covered="true" index="10" text="Line 185" weight="0" sourceline="1" />
358
Element JavaDoc mEl = doc.createElement( T_MARK );
359         parentEl.appendChild( mEl );
360         
361         mEl.setAttribute( A_MEASURE, mark.measureName );
362         mEl.setAttribute( A_COVERED, mark.current.getAttribute( A_COVERED ) );
363         mEl.setAttribute( A_INDEX, mark.current.getAttribute( A_INDEX ) );
364         mEl.setAttribute( A_TEXT, mark.current.getAttribute( A_TEXT ) );
365         mEl.setAttribute( A_WEIGHT, mark.current.getAttribute( A_WEIGHT ) );
366         mEl.setAttribute( A_SOURCELINE, mark.current.getAttribute( A_SOURCELINE ) );
367     }
368     
369     
370     /**
371      * Join a package element together
372      */

373     private void joinPackage( Document JavaDoc doc, Element JavaDoc parentEl, ReportSet reports )
374     {
375         Iterator JavaDoc iter = reports.getMeasureNames();
376         if (!iter.hasNext())
377         {
378             throw new IllegalStateException JavaDoc("No package elements.");
379         }
380         Element JavaDoc packageEl = doc.createElement( T_PACKAGE );
381         parentEl.appendChild( packageEl );
382         
383         Report r = reports.nextReport( iter );
384         iter = null;
385         packageEl.setAttribute( A_NAME, r.current.getAttribute( A_NAME ) );
386         r = null;
387         
388         joinCoverage( doc, packageEl, reports.getFirst( T_COVER ) );
389     }
390     
391     private void joinCoverage( Document JavaDoc doc, Element JavaDoc parentEl, ReportSet reports )
392     {
393         joinCoverage( doc, parentEl, reports, false );
394     }
395     
396     /**
397      * Join the coverage numbers together.
398      */

399     private void joinCoverage( Document JavaDoc doc, Element JavaDoc parentEl, ReportSet reports, boolean debug )
400     {
401         Element JavaDoc coverEl = doc.createElement( T_COVER );
402         parentEl.appendChild( coverEl );
403         if (debug)
404         {
405             System.out.println("jc: Adding coverage to "+parentEl.getTagName());
406         }
407         
408         Iterator JavaDoc iter = reports.getMeasureNames();
409         int measureCount = 0;
410         int coveredCount = 0;
411         int totalCount = 0;
412         double weightedPercentTotal = 0.0;
413         while (iter.hasNext())
414         {
415             Report r = reports.nextReport( iter );
416             if (debug)
417             {
418                 System.out.println("jc: - Adding measure "+r.measureName);
419                 System.out.println("jc: - measure parent = "+
420                     ((Element JavaDoc)r.current.getParentNode()).getTagName());
421             }
422             Element JavaDoc modCoverEl = doc.createElement( T_MODULECOVER );
423             coverEl.appendChild( modCoverEl );
424             modCoverEl.setAttribute( A_MEASURE, r.measureName );
425             
426             Element JavaDoc cur = r.current;
427             ++measureCount;
428             coveredCount += parseI( cur.getAttribute( A_COVERED ) );
429             totalCount += parseI( cur.getAttribute( A_TOTAL ) );
430             weightedPercentTotal += parseD( cur.getAttribute( A_WEIGHTEDPERCENT ) );
431             
432             modCoverEl.setAttribute( A_COVERED_DISP, cur.getAttribute( A_COVERED_DISP ) );
433             modCoverEl.setAttribute( A_COVERED, cur.getAttribute( A_COVERED ) );
434             modCoverEl.setAttribute( A_TOTAL_DISP, cur.getAttribute( A_TOTAL_DISP ) );
435             modCoverEl.setAttribute( A_TOTAL, cur.getAttribute( A_TOTAL ) );
436             modCoverEl.setAttribute( A_PERCENTCOVERED_DISP, cur.getAttribute( A_PERCENTCOVERED_DISP ) );
437             modCoverEl.setAttribute( A_PERCENTCOVERED, cur.getAttribute( A_PERCENTCOVERED ) );
438             modCoverEl.setAttribute( A_WEIGHTEDPERCENT_DISP, cur.getAttribute( A_WEIGHTEDPERCENT_DISP ) );
439             modCoverEl.setAttribute( A_WEIGHTEDPERCENT, cur.getAttribute( A_WEIGHTEDPERCENT ) );
440         }
441         
442         double perc = 100.0;
443         if (totalCount > 0)
444         {
445             perc = (double)coveredCount * 100.0 / (double)totalCount;
446         }
447         
448         // not totally accurate, but it works, and the value isn't used right now
449
double weight = 100.0;
450         if (measureCount > 0)
451         {
452             weight = weightedPercentTotal / (double)measureCount;
453         }
454         
455         coverEl.setAttribute( A_COVERED_DISP, format( coveredCount ) );
456         coverEl.setAttribute( A_COVERED, formatNumber( coveredCount ) );
457         coverEl.setAttribute( A_TOTAL_DISP, format( totalCount ) );
458         coverEl.setAttribute( A_TOTAL, formatNumber( totalCount ) );
459         coverEl.setAttribute( A_PERCENTCOVERED_DISP, format( perc ) );
460         coverEl.setAttribute( A_PERCENTCOVERED, formatNumber( perc ) );
461         coverEl.setAttribute( A_WEIGHTEDPERCENT_DISP, format( weight ) );
462         coverEl.setAttribute( A_WEIGHTEDPERCENT, formatNumber( weight ) );
463     }
464     
465     
466     //-----------------------------------------------------------------------
467
// Helper / utilities
468

469     
470     private String JavaDoc format( int i )
471     {
472         return IFORMAT.format( (long)i );
473     }
474     
475     
476     private String JavaDoc format( double d )
477     {
478         return DFORMAT.format( d );
479     }
480     
481     
482     private String JavaDoc formatNumber( int i )
483     {
484         return Integer.toString( i );
485     }
486     
487     
488     private String JavaDoc formatNumber( double d )
489     {
490         return Double.toString( d );
491     }
492     
493     
494     private int parseI( String JavaDoc s )
495     {
496         try
497         {
498             return IFORMAT.parse( s ).intValue();
499         }
500         catch (java.text.ParseException JavaDoc e)
501         {
502             throw new IllegalStateException JavaDoc( "Expected an integer, but found "+
503                 s );
504         }
505     }
506     
507     
508     private double parseD( String JavaDoc s )
509     {
510         try
511         {
512             return DFORMAT.parse( s ).doubleValue();
513         }
514         catch (java.text.ParseException JavaDoc e)
515         {
516             throw new IllegalStateException JavaDoc( "Expected a number, but found "+
517                 s );
518         }
519     }
520     
521     
522     private ReportSet[] sort( ReportSet reports, String JavaDoc tagName,
523             String JavaDoc attrName )
524     {
525         Map JavaDoc reportsByPackage = new HashMap JavaDoc();
526         Iterator JavaDoc iter = reports.getMeasureNames();
527         while (iter.hasNext())
528         {
529             Report r = reports.nextReport( iter );
530             Report[] subs = r.getAll( tagName );
531             for (int i = 0; i < subs.length; ++i)
532             {
533                 String JavaDoc val = subs[i].current.getAttribute( attrName );
534                 List JavaDoc s = (List JavaDoc)reportsByPackage.get( val );
535                 if (s == null)
536                 {
537                     s = new LinkedList JavaDoc();
538                     reportsByPackage.put( val, s );
539                 }
540                 s.add( subs[i] );
541             }
542         }
543         List JavaDoc sets = new LinkedList JavaDoc();
544         iter = reportsByPackage.values().iterator();
545         while (iter.hasNext())
546         {
547             List JavaDoc rep = (List JavaDoc)iter.next();
548             ReportSet rs = new ReportSet( (Report[])rep.toArray(
549                 new Report[ rep.size() ] ) );
550             sets.add( rs );
551         }
552         return (ReportSet[])sets.toArray( new ReportSet[ sets.size() ] );
553     }
554     
555     
556     private static DocumentBuilder JavaDoc getDocumentBuilder() {
557         try {
558             return DocumentBuilderFactory.newInstance().newDocumentBuilder();
559         } catch (Exception JavaDoc exc) {
560             throw new ExceptionInInitializerError JavaDoc(exc);
561         }
562     }
563 }
564
565
Popular Tags