KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > vladium > emma > report > xml > ReportGenerator


1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: ReportGenerator.java,v 1.1.1.1.2.1 2004/07/16 23:32:29 vlad_r Exp $
8  */

9 package com.vladium.emma.report.xml;
10
11 import java.io.BufferedWriter JavaDoc;
12 import java.io.File JavaDoc;
13 import java.io.FileOutputStream JavaDoc;
14 import java.io.IOException JavaDoc;
15 import java.io.OutputStreamWriter JavaDoc;
16 import java.io.UnsupportedEncodingException JavaDoc;
17 import java.io.Writer JavaDoc;
18 import java.util.Date JavaDoc;
19 import java.util.Iterator JavaDoc;
20
21 import com.vladium.util.Files;
22 import com.vladium.util.IConstants;
23 import com.vladium.util.IProperties;
24 import com.vladium.util.Strings;
25 import com.vladium.emma.IAppConstants;
26 import com.vladium.emma.IAppErrorCodes;
27 import com.vladium.emma.EMMAProperties;
28 import com.vladium.emma.EMMARuntimeException;
29 import com.vladium.emma.data.ICoverageData;
30 import com.vladium.emma.data.IMetaData;
31 import com.vladium.emma.report.AbstractReportGenerator;
32 import com.vladium.emma.report.AllItem;
33 import com.vladium.emma.report.ClassItem;
34 import com.vladium.emma.report.IItem;
35 import com.vladium.emma.report.IItemAttribute;
36 import com.vladium.emma.report.IItemMetadata;
37 import com.vladium.emma.report.ItemComparator;
38 import com.vladium.emma.report.MethodItem;
39 import com.vladium.emma.report.PackageItem;
40 import com.vladium.emma.report.SourcePathCache;
41 import com.vladium.emma.report.SrcFileItem;
42
43 // ----------------------------------------------------------------------------
44
/**
45  * @author Vlad Roubtsov, (C) 2003
46  */

47 public
48 final class ReportGenerator extends AbstractReportGenerator
49                             implements IAppErrorCodes
50 {
51     // public: ................................................................
52

53     // IReportGenerator:
54

55     public String JavaDoc getType ()
56     {
57         return TYPE;
58     }
59     
60     public void process (final IMetaData mdata, final ICoverageData cdata,
61                          final SourcePathCache cache, final IProperties properties)
62         throws EMMARuntimeException
63     {
64         initialize (mdata, cdata, cache, properties);
65         
66         long start = 0, end;
67         final boolean trace1 = m_log.atTRACE1 ();
68         
69         if (trace1) start = System.currentTimeMillis ();
70         
71         {
72             m_view.getRoot ().accept (this, null);
73             close ();
74         }
75                 
76         if (trace1)
77         {
78             end = System.currentTimeMillis ();
79             
80             m_log.trace1 ("process", "[" + getType () + "] report generated in " + (end - start) + " ms");
81         }
82     }
83     
84     public void cleanup ()
85     {
86         close ();
87         
88         super.cleanup ();
89     }
90     
91     
92     // IItemVisitor:
93

94     public Object JavaDoc visit (final AllItem item, final Object JavaDoc ctx)
95     {
96         try
97         {
98             File JavaDoc outFile = m_settings.getOutFile ();
99             if (outFile == null)
100             {
101                 outFile = new File JavaDoc ("coverage.xml");
102                 m_settings.setOutFile (outFile);
103             }
104             
105             final File JavaDoc fullOutFile = Files.newFile (m_settings.getOutDir (), outFile);
106             
107             m_log.info ("writing [" + getType () + "] report to [" + fullOutFile.getAbsolutePath () + "] ...");
108             
109             openOutFile (fullOutFile, m_settings.getOutEncoding (), true);
110             
111             // XML header:
112
m_out.write ("<?xml version=\"1.0\" encoding=\"" + m_settings.getOutEncoding () + "\"?>");
113             
114             // build ID stamp:
115
try
116             {
117                 final StringBuffer JavaDoc label = new StringBuffer JavaDoc (101);
118                 
119                 label.append ("<!-- ");
120                 label.append (IAppConstants.APP_NAME);
121                 label.append (" v"); label.append (IAppConstants.APP_VERSION_WITH_BUILD_ID_AND_TAG);
122                 label.append (" report, generated ");
123                 label.append (new Date JavaDoc (EMMAProperties.getTimeStamp ()));
124                 label.append (" -->");
125                 
126                 m_out.write (label.toString ());
127                 m_out.newLine ();
128                 
129                 m_out.flush ();
130             }
131             catch (IOException JavaDoc ioe)
132             {
133                 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe);
134             }
135             
136             eol ();
137             openElementTag ("report");
138             closeElementTag (false);
139             m_out.incIndent ();
140             
141             // stats summary section:
142
eol ();
143             openElementTag ("stats");
144             closeElementTag (false);
145             m_out.incIndent ();
146             {
147                 emitStatsCount ("packages", item.getChildCount ());
148                 emitStatsCount ("classes", item.getAggregate (IItem.TOTAL_CLASS_COUNT));
149                 emitStatsCount ("methods", item.getAggregate (IItem.TOTAL_METHOD_COUNT));
150                 
151                 if (m_srcView && m_hasSrcFileInfo)
152                 {
153                     emitStatsCount ("srcfiles", item.getAggregate (IItem.TOTAL_SRCFILE_COUNT));
154                     
155                     if (m_hasLineNumberInfo)
156                         emitStatsCount ("srclines", item.getAggregate (IItem.TOTAL_LINE_COUNT));
157                 }
158             }
159             m_out.decIndent ();
160             eol ();
161             endElement ("stats");
162             
163             // actual coverage data:
164
eol ();
165             openElementTag ("data");
166             closeElementTag (false);
167             m_out.incIndent ();
168             {
169                 final ItemComparator childrenOrder = m_typeSortComparators [PackageItem.getTypeMetadata ().getTypeID ()];
170                 emitItem (item, childrenOrder);
171             }
172             m_out.decIndent ();
173             eol ();
174             endElement ("data");
175             
176             m_out.decIndent ();
177             eol ();
178             endElement ("report");
179         }
180         catch (IOException JavaDoc ioe)
181         {
182             throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe);
183         }
184
185         return ctx;
186     }
187     
188     
189     public Object JavaDoc visit (final PackageItem item, final Object JavaDoc ctx)
190     {
191         if (m_verbose) m_log.verbose (" report: processing package [" + item.getName () + "] ...");
192         
193         try
194         {
195             final ItemComparator childrenOrder = m_typeSortComparators [m_srcView ? SrcFileItem.getTypeMetadata ().getTypeID () : ClassItem.getTypeMetadata ().getTypeID ()];
196             emitItem (item, childrenOrder);
197         }
198         catch (IOException JavaDoc ioe)
199         {
200             throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe);
201         }
202
203         return ctx;
204     }
205     
206     
207     public Object JavaDoc visit (final SrcFileItem item, final Object JavaDoc ctx)
208     {
209         try
210         {
211             final ItemComparator childrenOrder = m_typeSortComparators [ClassItem.getTypeMetadata ().getTypeID ()];
212             emitItem (item, childrenOrder);
213         }
214         catch (IOException JavaDoc ioe)
215         {
216             throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe);
217         }
218
219         return ctx;
220     }
221
222     public Object JavaDoc visit (final ClassItem item, final Object JavaDoc ctx)
223     {
224         try
225         {
226             final ItemComparator childrenOrder = m_typeSortComparators [MethodItem.getTypeMetadata ().getTypeID ()];
227             emitItem (item, childrenOrder);
228         }
229         catch (IOException JavaDoc ioe)
230         {
231             throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe);
232         }
233
234         return ctx;
235     }
236     
237     public Object JavaDoc visit (final MethodItem item, final Object JavaDoc ctx)
238     {
239         try
240         {
241             emitItem (item, null);
242         }
243         catch (IOException JavaDoc ioe)
244         {
245             throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe);
246         }
247
248         return ctx;
249     }
250         
251     // protected: .............................................................
252

253     // package: ...............................................................
254

255     // private: ...............................................................
256

257     
258     private static final class IndentingWriter extends BufferedWriter JavaDoc
259     {
260         public void newLine () throws IOException JavaDoc
261         {
262             m_state = 0;
263             super.write (IConstants.EOL, 0, IConstants.EOL.length ());
264         }
265                 
266         public void write (final char [] cbuf, final int off, final int len) throws IOException JavaDoc
267         {
268             indent ();
269             super.write (cbuf, off, len);
270         }
271
272         public void write (int c) throws IOException JavaDoc
273         {
274             indent ();
275             super.write (c);
276         }
277
278         public void write (final String JavaDoc s, final int off, final int len) throws IOException JavaDoc
279         {
280             indent ();
281             super.write (s, off, len);
282         }
283
284         
285         IndentingWriter (final Writer JavaDoc out, final int buffer, final int indent)
286         {
287             super (out, buffer);
288             m_indent = indent;
289         }
290
291         
292         void incIndent (final int delta)
293         {
294             if (delta < 0) throw new IllegalArgumentException JavaDoc ("delta be non-negative: " + delta);
295             
296             m_indent += delta;
297         }
298         
299         void incIndent ()
300         {
301             incIndent (INDENT_INCREMENT);
302         }
303         
304         void decIndent (final int delta)
305         {
306             if (delta < 0) throw new IllegalArgumentException JavaDoc ("delta be non-negative: " + delta);
307             if (delta > m_indent) throw new IllegalArgumentException JavaDoc ("delta = " + delta + ", current indent = " + m_indent);
308             
309             m_indent -= delta;
310         }
311         
312         void decIndent ()
313         {
314             decIndent (INDENT_INCREMENT);
315         }
316         
317         String JavaDoc getIndent ()
318         {
319             if (m_indent <= 0)
320                 return "";
321             else
322             {
323                 if ((m_sindent == null) || (m_sindent.length () < m_indent))
324                 {
325                     final char [] ca = new char [m_indent];
326                     
327                     for (int i = 0; i < m_indent; ++ i) ca [i] = ' ';
328                     m_sindent = new String JavaDoc (ca);
329                     
330                     return m_sindent;
331                 }
332                 else
333                 {
334                     return m_sindent.substring (0, m_indent);
335                 }
336             }
337         }
338         
339                 
340         private void indent ()
341             throws IOException JavaDoc
342         {
343             if (m_state == 0)
344             {
345                 final String JavaDoc indent = getIndent ();
346                 super.write (indent, 0, indent.length ());
347                 
348                 m_state = 1;
349             }
350         }
351         
352         
353         private int m_indent;
354         private int m_state;
355         private transient String JavaDoc m_sindent;
356         
357         private static final int INDENT_INCREMENT = 2;
358         
359     } // end of nested class
360

361     
362     private void emitStatsCount (final String JavaDoc name, final int value)
363         throws IOException JavaDoc
364     {
365         eol ();
366         openElementTag (name);
367         m_out.write (" value=\"" + value);
368         m_out.write ('"');
369         closeElementTag (true);
370     }
371
372     private void emitItem (final IItem item, final ItemComparator childrenOrder)
373         throws IOException JavaDoc
374     {
375         final IItemMetadata metadata = item.getMetadata ();
376         final int [] columns = m_settings.getColumnOrder ();
377         final String JavaDoc tag = metadata.getTypeName ();
378  
379         eol ();
380         
381         // emit opening tag with name attribute:
382
{
383             openElementTag (tag);
384             
385             m_out.write (" name=\"");
386             m_out.write (Strings.HTMLEscape (item.getName ()));
387             m_out.write ('"');
388             
389             closeElementTag (false);
390         }
391         
392         eol ();
393             
394         m_out.incIndent ();
395
396         emitItemCoverage (item, columns);
397         
398         final boolean deeper = (childrenOrder != null) && (m_settings.getDepth () > metadata.getTypeID ()) && (item.getChildCount () > 0);
399         
400         if (deeper)
401         {
402             for (Iterator JavaDoc packages = item.getChildren (childrenOrder); packages.hasNext (); )
403             {
404                 ((IItem) packages.next ()).accept (this, null);
405             }
406             
407             eol ();
408         }
409
410         m_out.decIndent ();
411         
412         // emit closing tag:
413
{
414             endElement (tag);
415         }
416     }
417     
418     /*
419      * No header row, just data rows.
420      */

421     private void emitItemCoverage (final IItem item, final int [] columns)
422         throws IOException JavaDoc
423     {
424         final StringBuffer JavaDoc buf = new StringBuffer JavaDoc (64);
425         
426         for (int c = 0, cLimit = columns.length; c < cLimit; ++ c)
427         {
428             final int attrID = columns [c];
429             
430             if (attrID != IItemAttribute.ATTRIBUTE_NAME_ID)
431             {
432                 final IItemAttribute attr = item.getAttribute (attrID, m_settings.getUnitsType ());
433                 
434                 if (attr != null)
435                 {
436                     openElementTag ("coverage");
437
438                     m_out.write (" type=\"");
439                     m_out.write (Strings.HTMLEscape (attr.getName ()));
440                     m_out.write ("\" value=\"");
441                     attr.format (item, buf);
442                     m_out.write (Strings.HTMLEscape (buf.toString ()));
443                     m_out.write ('"');
444                     buf.setLength (0);
445                     
446                     closeElementTag (true);
447                     
448                     eol ();
449                 }
450             }
451         }
452         
453     }
454     
455     private void openElementTag (final String JavaDoc tag)
456         throws IOException JavaDoc
457     {
458         m_out.write ('<');
459         m_out.write (tag);
460     }
461     
462     private void closeElementTag (final boolean simple)
463         throws IOException JavaDoc
464     {
465         if (simple)
466             m_out.write ("/>");
467         else
468             m_out.write ('>');
469     }
470     
471     private void endElement (final String JavaDoc tag)
472         throws IOException JavaDoc
473     {
474         m_out.write ("</");
475         m_out.write (tag);
476         m_out.write ('>');
477     }
478     
479     private void eol ()
480         throws IOException JavaDoc
481     {
482         m_out.newLine ();
483     }
484     
485     private void close ()
486     {
487         if (m_out != null)
488         {
489             try
490             {
491                 m_out.flush ();
492                 m_out.close ();
493             }
494             catch (IOException JavaDoc ioe)
495             {
496                 throw new EMMARuntimeException (IAppErrorCodes.REPORT_IO_FAILURE, ioe);
497             }
498             finally
499             {
500                 m_out = null;
501             }
502         }
503     }
504     
505     private void openOutFile (final File JavaDoc file, final String JavaDoc encoding, final boolean mkdirs)
506     {
507         try
508         {
509             if (mkdirs)
510             {
511                 final File JavaDoc parent = file.getParentFile ();
512                 if (parent != null) parent.mkdirs ();
513             }
514             
515             m_out = new IndentingWriter (new OutputStreamWriter JavaDoc (new FileOutputStream JavaDoc (file), encoding), IO_BUF_SIZE, 0);
516         }
517         catch (UnsupportedEncodingException JavaDoc uee)
518         {
519             // TODO: error code
520
throw new EMMARuntimeException (uee);
521         }
522         // note: in J2SDK 1.3 FileOutputStream constructor's throws clause
523
// was narrowed to FileNotFoundException:
524
catch (IOException JavaDoc fnfe) // FileNotFoundException
525
{
526             // TODO: error code
527
throw new EMMARuntimeException (fnfe);
528         }
529     }
530     
531     
532     private IndentingWriter m_out;
533     
534     private static final String JavaDoc TYPE = "xml";
535     private static final int IO_BUF_SIZE = 64 * 1024;
536
537 } // end of class
538
// ----------------------------------------------------------------------------
Popular Tags