View Javadoc

1   package org.codehaus.mojo.dashboard.report.plugin;
2   
3   /*
4    * Copyright 2006 David Vicente
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.IOException;
20  import java.text.SimpleDateFormat;
21  import java.util.Collections;
22  import java.util.Date;
23  import java.util.Hashtable;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.ResourceBundle;
28  import java.util.Set;
29  
30  import org.apache.maven.plugin.logging.Log;
31  
32  import org.codehaus.doxia.sink.Sink;
33  import org.codehaus.mojo.dashboard.report.plugin.beans.CheckstyleError;
34  import org.codehaus.mojo.dashboard.report.plugin.beans.CheckstyleReportBean;
35  import org.codehaus.mojo.dashboard.report.plugin.beans.CloverReportBean;
36  import org.codehaus.mojo.dashboard.report.plugin.beans.CoberturaReportBean;
37  import org.codehaus.mojo.dashboard.report.plugin.beans.CpdReportBean;
38  import org.codehaus.mojo.dashboard.report.plugin.beans.DashBoardMavenProject;
39  import org.codehaus.mojo.dashboard.report.plugin.beans.FindBugsReportBean;
40  import org.codehaus.mojo.dashboard.report.plugin.beans.IDashBoardReportBean;
41  import org.codehaus.mojo.dashboard.report.plugin.beans.JDependReportBean;
42  import org.codehaus.mojo.dashboard.report.plugin.beans.PmdReportBean;
43  import org.codehaus.mojo.dashboard.report.plugin.beans.SurefireReportBean;
44  import org.codehaus.mojo.dashboard.report.plugin.beans.TagListReportBean;
45  import org.codehaus.mojo.dashboard.report.plugin.beans.XRefPackageBean;
46  import org.codehaus.mojo.dashboard.report.plugin.beans.comparator.DescNbErrorCheckstyleComparator;
47  import org.codehaus.mojo.dashboard.report.plugin.chart.BarChartRenderer;
48  import org.codehaus.mojo.dashboard.report.plugin.chart.CheckstyleErrorsPieChartStrategy;
49  import org.codehaus.mojo.dashboard.report.plugin.chart.CheckstylePieChartStrategy;
50  import org.codehaus.mojo.dashboard.report.plugin.chart.CloverBarChartStrategy;
51  import org.codehaus.mojo.dashboard.report.plugin.chart.CoberturaBarChartStrategy;
52  import org.codehaus.mojo.dashboard.report.plugin.chart.FindbugsCategoriesPieChartStrategy;
53  import org.codehaus.mojo.dashboard.report.plugin.chart.FindbugsPrioritiesPieChartStrategy;
54  import org.codehaus.mojo.dashboard.report.plugin.chart.IChartRenderer;
55  import org.codehaus.mojo.dashboard.report.plugin.chart.PieChart3DRenderer;
56  import org.codehaus.mojo.dashboard.report.plugin.chart.PieChartRenderer;
57  import org.codehaus.mojo.dashboard.report.plugin.chart.SurefirePieChartStrategy;
58  import org.codehaus.mojo.dashboard.report.plugin.chart.TaglistPieChartStrategy;
59  import org.codehaus.mojo.dashboard.report.plugin.utils.ChartUtils;
60  
61  /**
62   * <ul>
63   * <li>Add "CheckStyle Violations" graph written by <a href="mailto:srivollet@objectif-informatique.fr">Sylvain
64   * Rivollet</a></li>
65   * <li>Add Clover support written by <a href="mailto:mbeerman@yahoo.com">Matthew Beermann</a></li>
66   * <li>Add Taglist support written by <a href="mailto:henrik.lynggaard@gmail.com">Henrik Lynggaard</a></li>
67   * </ul>
68   *
69   * @author <a href="dvicente72@gmail.com">David Vicente</a>
70   */
71  public class DashBoardReportGenerator extends AbstractDashBoardGenerator
72  {
73      /**
74       *
75       */
76      private static final int SPECIFIC_WIDTH = 600;
77  
78      /**
79       *
80       */
81      private final DashBoardMavenProject mavenProject;
82  
83      private final Map map = new Hashtable();
84  
85      private boolean isDBAvailable = false;
86  
87      private boolean generateGraphs = true;
88  
89      /**
90       *
91       */
92      private boolean summary = false;
93  
94      public DashBoardReportGenerator( DashBoardMavenProject mavenProject, boolean summary, boolean isDBAvailable,
95                                       boolean generateGraphs, Log log )
96      {
97          super( log );
98          this.mavenProject = mavenProject;
99          this.summary = summary;
100         this.isDBAvailable = isDBAvailable;
101         this.generateGraphs = generateGraphs;
102         Set reports = mavenProject.getReports();
103         Iterator iter = reports.iterator();
104         while ( iter.hasNext() )
105         {
106             IDashBoardReportBean report = (IDashBoardReportBean) iter.next();
107             if ( report != null )
108             {
109                 this.map.put( report.getClass(), report );
110             }
111         }
112 
113     }
114 
115     public void doGenerateReport( ResourceBundle bundle, Sink sink )
116     {
117 
118         this.createTitle( bundle, sink );
119         addDashboardCss(sink);
120         sink.body();
121         sink.anchor( "top" );
122         sink.anchor_();
123         this.createHeader( bundle, sink );
124 
125         if ( this.map.get( CoberturaReportBean.class ) != null )
126         {
127             this.createCoberturaSection( bundle, sink, (CoberturaReportBean) this.map.get( CoberturaReportBean.class ) );
128         }
129         if ( this.map.get( CloverReportBean.class ) != null )
130         {
131             this.createCloverSection( bundle, sink, (CloverReportBean) this.map.get( CloverReportBean.class ) );
132         }
133         if ( this.map.get( SurefireReportBean.class ) != null )
134         {
135             this.createSurefireSection( bundle, sink, (SurefireReportBean) this.map.get( SurefireReportBean.class ) );
136         }
137         if ( this.map.get( CheckstyleReportBean.class ) != null )
138         {
139             this.createCheckStyleSection( bundle, sink,
140                                           (CheckstyleReportBean) this.map.get( CheckstyleReportBean.class ) );
141         }
142         if ( this.map.get( PmdReportBean.class ) != null )
143         {
144             this.createPmdSection( bundle, sink, (PmdReportBean) this.map.get( PmdReportBean.class ) );
145         }
146         if ( this.map.get( CpdReportBean.class ) != null )
147         {
148             this.createCpdSection( bundle, sink, (CpdReportBean) this.map.get( CpdReportBean.class ) );
149         }
150         if ( this.map.get( FindBugsReportBean.class ) != null )
151         {
152             this.createFindBugsSection( bundle, sink, (FindBugsReportBean) this.map.get( FindBugsReportBean.class ) );
153         }
154         if ( this.map.get( JDependReportBean.class ) != null )
155         {
156             this.createJDependSection( bundle, sink, (JDependReportBean) this.map.get( JDependReportBean.class ) );
157         }
158         if ( this.map.get( TagListReportBean.class ) != null )
159         {
160             this.createTaglistSection( bundle, sink, (TagListReportBean) this.map.get( TagListReportBean.class ) );
161         }
162 
163         sink.body_();
164 
165         sink.flush();
166 
167         sink.close();
168     }
169 
170     public void createTitle( ResourceBundle bundle, Sink sink )
171     {
172         sink.head();
173         sink.title();
174         sink.text( bundle.getString( "dashboard.report.name" ) );
175         sink.title_();
176         sink.head_();
177     }
178 
179     public void createHeader( ResourceBundle bundle, Sink sink )
180     {
181         sink.section1();
182 
183         sink.sectionTitle1();
184         sink.text( bundle.getString( "dashboard.report.name" ) );
185         sink.sectionTitle1_();
186 
187         sink.text( "Date Generated: " + new SimpleDateFormat().format( new Date( System.currentTimeMillis() ) ) );
188         sink.horizontalRule();
189 
190         if ( this.summary )
191         {
192             sink.sectionTitle3();
193             sink.text( "[" );
194             sink.link( "dashboard-report-details.html" );
195             sink.text( "Detailed Dashboard" );
196             sink.link_();
197             sink.text( "]" );
198             sink.sectionTitle3_();
199             sink.horizontalRule();
200         }
201 
202         if ( this.map.get( CoberturaReportBean.class ) != null )
203         {
204             sink.text( "[" );
205             sink.link( "#cobertura" );
206             sink.text( bundle.getString( "report.cobertura.header" ) );
207             sink.link_();
208             sink.text( "]" );
209             sink.lineBreak();
210         }
211         if ( this.map.get( CloverReportBean.class ) != null )
212         {
213             sink.text( "[" );
214             sink.link( "#clover" );
215             sink.text( bundle.getString( "report.clover.header" ) );
216             sink.link_();
217             sink.text( "]" );
218             sink.lineBreak();
219         }
220         if ( this.map.get( SurefireReportBean.class ) != null )
221         {
222             sink.text( "[" );
223             sink.link( "#surefire" );
224             sink.text( bundle.getString( "report.surefire.header" ) );
225             sink.link_();
226             sink.text( "]" );
227             sink.lineBreak();
228         }
229         if ( this.map.get( CheckstyleReportBean.class ) != null )
230         {
231             sink.text( "[" );
232             sink.link( "#checkstyle" );
233             sink.text( bundle.getString( "report.checkstyle.header" ) );
234             sink.link_();
235             sink.text( "]" );
236             sink.lineBreak();
237         }
238         if ( this.map.get( PmdReportBean.class ) != null )
239         {
240             sink.text( "[" );
241             sink.link( "#pmd" );
242             sink.text( bundle.getString( "report.pmd.header" ) );
243             sink.link_();
244             sink.text( "]" );
245             sink.lineBreak();
246         }
247         if ( this.map.get( CpdReportBean.class ) != null )
248         {
249             sink.text( "[" );
250             sink.link( "#cpd" );
251             sink.text( bundle.getString( "report.cpd.header" ) );
252             sink.link_();
253             sink.text( "]" );
254             sink.lineBreak();
255         }
256         if ( this.map.get( FindBugsReportBean.class ) != null )
257         {
258             sink.text( "[" );
259             sink.link( "#findbugs" );
260             sink.text( bundle.getString( "report.findbugs.header" ) );
261             sink.link_();
262             sink.text( "]" );
263             sink.lineBreak();
264         }
265         if ( this.map.get( JDependReportBean.class ) != null )
266         {
267             sink.text( "[" );
268             sink.link( "#jdepend" );
269             sink.text( bundle.getString( "report.xrefpackage.header" ) );
270             sink.link_();
271             sink.text( "]" );
272             sink.lineBreak();
273         }
274 
275         if ( this.map.get( TagListReportBean.class ) != null )
276         {
277             sink.text( "[" );
278             sink.link( "#taglist" );
279             sink.text( bundle.getString( "report.taglist.header" ) );
280             sink.link_();
281             sink.text( "]" );
282             sink.lineBreak();
283         }
284 
285         sink.horizontalRule();
286         sink.lineBreak();
287 
288         if ( !this.generateGraphs )
289         {
290             sink.text( "[" + bundle.getString( "dashboard.report.generategraphs.disabled" ) + "]" );
291             sink.lineBreak();
292         }
293 
294         sink.section1_();
295     }
296 
297     public void createSurefireSection( ResourceBundle bundle, Sink sink, SurefireReportBean report )
298     {
299 
300         sink.section1();
301 
302         sink.sectionTitle2();
303         sink.anchor( "surefire" );
304         sink.anchor_();
305         if ( this.summary )
306         {
307             sink.link( "dashboard-report-details.html#surefire" );
308             sink.text( bundle.getString( "report.surefire.header" ) );
309             sink.link_();
310         }
311         else
312         {
313             sink.link( "./surefire-report.html" );
314             sink.text( bundle.getString( "report.surefire.header" ) );
315             sink.link_();
316         }
317         sink.sectionTitle2_();
318         this.linkToTopPage( sink );
319         sink.lineBreak();
320         if ( this.isDBAvailable )
321         {
322             this.linkToHistoricPage( sink, "surefire" );
323         }
324         sink.section1_();
325         sink.lineBreak();
326         sink.table();
327         sink.tableRow();
328 
329         this.sinkHeader( sink, bundle.getString( "report.surefire.label.successrate" ) );
330 
331         this.sinkHeader( sink, bundle.getString( "report.surefire.label.tests" ) );
332 
333         this.sinkHeader( sink, bundle.getString( "report.surefire.label.errors" ) );
334 
335         this.sinkHeader( sink, bundle.getString( "report.surefire.label.failures" ) );
336 
337         this.sinkHeader( sink, bundle.getString( "report.surefire.label.skipped" ) );
338 
339         this.sinkHeader( sink, bundle.getString( "report.surefire.label.time" ) );
340 
341         sink.tableRow_();
342 
343         if ( report != null )
344         {
345             // List testSuites = report.parseXMLReportFiles();
346             // Map summary = report.getSummary( testSuites );
347             sink.tableRow();
348 
349             this.sinkCellPercentGraphic( sink, report.getSucessRate() / 100, "surefire" );
350 
351             this.sinkCell( sink, Integer.toString( report.getNbTests() ) );
352 
353             this.sinkCell( sink, Integer.toString( report.getNbErrors() ) );
354 
355             this.sinkCell( sink, Integer.toString( report.getNbFailures() ) );
356 
357             this.sinkCell( sink, Integer.toString( report.getNbSkipped() ) );
358 
359             this.sinkCell( sink, Double.toString( report.getElapsedTime() ) );
360 
361             sink.tableRow_();
362         }
363         else
364         {
365             sink.tableRow();
366 
367             this.sinkCell( sink, "0" );
368 
369             this.sinkCell( sink, "0" );
370 
371             this.sinkCell( sink, "0" );
372 
373             this.sinkCell( sink, "0" );
374 
375             this.sinkCell( sink, "0" + "%" );
376 
377             this.sinkCell( sink, "0" );
378 
379             sink.tableRow_();
380         }
381 
382         sink.table_();
383 
384         sink.lineBreak();
385         if ( this.generateGraphs )
386         {
387             IChartRenderer chart =
388                 new PieChartRenderer(
389                                       new SurefirePieChartStrategy( bundle, this.mavenProject.getProjectName(), report ),
390                                       DashBoardReportGenerator.SPECIFIC_WIDTH, ChartUtils.STANDARD_HEIGHT );
391             if ( !chart.isEmpty() )
392             {
393                 String filename = this.replaceForbiddenChar( this.mavenProject.getProjectName() );
394                 if ( this.summary )
395                 {
396                     filename += "_Summary_Surefire." + chart.getFileExtension();
397                 }
398                 else
399                 {
400                     filename += "_Surefire." + chart.getFileExtension();
401                 }
402                 filename = filename.replace( ' ', '_' );
403                 String filenameWithPath = this.getImagesPath() + "/" + filename;
404                 this.getLog().debug( "createSurefireGraph = " + filename );
405                 try
406                 {
407                     chart.saveToFile( filenameWithPath );
408                     String link = "images/" + filename;
409                     link = link.replace( ' ', '_' );
410                     sink.figure();
411                     sink.figureGraphics( link );
412                     sink.figure_();
413                 }
414                 catch ( IOException e )
415                 {
416                     this.getLog().debug( "createSurefireGraph exception = " + e.getMessage() );
417                 }
418             }
419         }
420         // else
421         // {
422         // sink.text("[" + bundle.getString("dashboard.report.generategraphs.disabled") + "]");
423         // sink.lineBreak();
424         // }
425     }
426 
427     /**
428      * Fixes MOJO-813. addition of Clover support. written by <a href="mailto:mbeerman@yahoo.com">Matthew Beermann</a>
429      *
430      * @param bundle
431      * @param sink
432      */
433     public void createCloverSection( ResourceBundle bundle, Sink sink, CloverReportBean report )
434     {
435         sink.section1();
436 
437         sink.sectionTitle2();
438         sink.anchor( "clover" );
439         sink.anchor_();
440         if ( this.summary )
441         {
442             sink.link( "dashboard-report-details.html#clover" );
443             sink.text( bundle.getString( "report.clover.header" ) );
444             sink.link_();
445         }
446         else
447         {
448             sink.link( "./clover/index.html" );
449             sink.text( bundle.getString( "report.clover.header" ) );
450             sink.link_();
451         }
452         sink.sectionTitle2_();
453         this.linkToTopPage( sink );
454         sink.lineBreak();
455         if ( this.isDBAvailable )
456         {
457             this.linkToHistoricPage( sink, "clover" );
458         }
459         sink.section1_();
460         sink.lineBreak();
461         sink.table();
462         sink.tableRow();
463 
464         this.sinkHeader( sink, bundle.getString( "report.clover.label.total" ) );
465 
466         this.sinkHeader( sink, bundle.getString( "report.clover.label.conditionals" ) );
467 
468         this.sinkHeader( sink, bundle.getString( "report.clover.label.statements" ) );
469 
470         this.sinkHeader( sink, bundle.getString( "report.clover.label.methods" ) );
471 
472         sink.tableRow_();
473 
474         if ( report != null )
475         {
476             sink.tableRow();
477 
478             if ( this.generateGraphs )
479             {
480 
481                 this.sinkCell( sink, report.getElementsLabel() );
482 
483                 this.sinkCell( sink, report.getConditionalsLabel() );
484 
485                 this.sinkCell( sink, report.getStatementsLabel() );
486 
487                 this.sinkCell( sink, report.getMethodsLabel() );
488 
489             }
490             else
491             {
492                 sink.tableCell();
493                 sinkPercentGraphic( sink, report.getPercentCoveredConditionals() );
494                 sink.text( "(" + report.getCoveredElements() + " / " + report.getElements() + ")" );
495                 sink.tableCell_();
496                 sink.tableCell();
497                 sinkPercentGraphic( sink, report.getPercentCoveredConditionals() );
498                 sink.text( "(" + report.getCoveredConditionals() + " / " + report.getConditionals() + ")" );
499                 sink.tableCell_();
500                 sink.tableCell();
501                 sinkPercentGraphic( sink, report.getPercentCoveredStatements() );
502                 sink.text( "(" + report.getCoveredStatements() + " / " + report.getStatements() + ")" );
503                 sink.tableCell_();
504                 sink.tableCell();
505                 sinkPercentGraphic( sink, report.getPercentCoveredMethods() );
506                 sink.text( "(" + report.getCoveredMethods() + " / " + report.getMethods() + ")" );
507                 sink.tableCell_();
508             }
509 
510             sink.tableRow_();
511         }
512         else
513         {
514             sink.tableRow();
515 
516             this.sinkCell( sink, "0" );
517 
518             this.sinkCell( sink, "0" );
519 
520             this.sinkCell( sink, "0" );
521 
522             this.sinkCell( sink, "0" );
523 
524             this.sinkCell( sink, "0" + "%" );
525 
526             this.sinkCell( sink, "0" );
527 
528             sink.tableRow_();
529         }
530         sink.table_();
531 
532         sink.lineBreak();
533         if ( this.generateGraphs )
534         {
535             Map datas = new Hashtable();
536             datas.put( this.mavenProject.getProjectName(), report );
537             IChartRenderer chart =
538                 new BarChartRenderer( new CloverBarChartStrategy( bundle, this.mavenProject.getProjectName(), datas ),
539                                       DashBoardReportGenerator.SPECIFIC_WIDTH + 50, ChartUtils.STANDARD_HEIGHT );
540             if ( !chart.isEmpty() )
541             {
542                 String filename = this.replaceForbiddenChar( this.mavenProject.getProjectName() );
543                 if ( this.summary )
544                 {
545                     filename += "_Summary_Clover." + chart.getFileExtension();
546                 }
547                 else
548                 {
549                     filename += "_Clover." + chart.getFileExtension();
550                 }
551                 filename = filename.replace( ' ', '_' );
552                 String filenameWithPath = this.getImagesPath() + "/" + filename;
553                 this.getLog().debug( "createCloverGraph = " + filename );
554                 try
555                 {
556                     chart.saveToFile( filenameWithPath );
557                     String link = "images/" + filename;
558                     link = link.replace( ' ', '_' );
559                     sink.figure();
560                     sink.figureGraphics( link );
561                     sink.figure_();
562                 }
563                 catch ( IOException e )
564                 {
565                     this.getLog().debug( "createCloverGraph exception = " + e.getMessage() );
566                 }
567             }
568         }
569         // else
570         // {
571         // sink.text("[" + bundle.getString("dashboard.report.generategraphs.disabled") + "]");
572         // sink.lineBreak();
573         // }
574     }
575 
576     public void createCoberturaSection( ResourceBundle bundle, Sink sink, CoberturaReportBean report )
577     {
578 
579         sink.section1();
580 
581         sink.sectionTitle2();
582         sink.anchor( "cobertura" );
583         sink.anchor_();
584         if ( this.summary )
585         {
586             sink.link( "dashboard-report-details.html#cobertura" );
587             sink.text( bundle.getString( "report.cobertura.header" ) );
588             sink.link_();
589         }
590         else
591         {
592             sink.link( "./cobertura/index.html" );
593             sink.text( bundle.getString( "report.cobertura.header" ) );
594             sink.link_();
595         }
596 
597         sink.sectionTitle2_();
598         this.linkToTopPage( sink );
599         sink.lineBreak();
600         if ( this.isDBAvailable )
601         {
602             this.linkToHistoricPage( sink, "cobertura" );
603         }
604         sink.section1_();
605         sink.lineBreak();
606         if ( report == null )
607         {
608             sink.text( "Error: Unable to read from Cobertura data file ." );
609         }
610         else
611         {
612             sink.table();
613             sink.tableRow();
614 
615             this.sinkHeader( sink, bundle.getString( "report.cobertura.label.nbclasses" ) );
616 
617             this.sinkHeader( sink, bundle.getString( "report.cobertura.label.linecover" ) );
618 
619             this.sinkHeader( sink, bundle.getString( "report.cobertura.label.branchcover" ) );
620 
621             sink.tableRow_();
622 
623             sink.tableRow();
624             this.sinkCell( sink, Integer.toString( report.getNbClasses() ) );
625 
626             if ( this.generateGraphs )
627             {
628                 this.sinkCell( sink, getPercentValue( report.getLineCoverRate() ) );
629                 this.sinkCell( sink, getPercentValue( report.getBranchCoverRate() ) );
630             }
631             else
632             {
633                 sinkCellPercentGraphic( sink, report.getLineCoverRate(), "cobertura" );
634                 sinkCellPercentGraphic( sink, report.getBranchCoverRate(), "cobertura" );
635             }
636 
637             sink.tableRow_();
638 
639             sink.table_();
640         }
641         sink.lineBreak();
642         if ( this.generateGraphs )
643         {
644             Map datas = new Hashtable();
645             datas.put( this.mavenProject.getProjectName(), report );
646             IChartRenderer chart =
647                 new BarChartRenderer(
648                                       new CoberturaBarChartStrategy( bundle, this.mavenProject.getProjectName(), datas ),
649                                       DashBoardReportGenerator.SPECIFIC_WIDTH + 50, ChartUtils.STANDARD_HEIGHT );
650             if ( !chart.isEmpty() )
651             {
652                 String filename = this.replaceForbiddenChar( this.mavenProject.getProjectName() );
653                 if ( this.summary )
654                 {
655                     filename += "_Summary_Cobertura." + chart.getFileExtension();
656                 }
657                 else
658                 {
659                     filename += "_Cobertura." + chart.getFileExtension();
660                 }
661                 filename = filename.replace( ' ', '_' );
662                 String filenameWithPath = this.getImagesPath() + "/" + filename;
663                 this.getLog().debug( "createCoberturaGraph = " + filename );
664                 try
665                 {
666                     chart.saveToFile( filenameWithPath );
667                     String link = "images/" + filename;
668                     link = link.replace( ' ', '_' );
669                     sink.figure();
670                     sink.figureGraphics( link );
671                     sink.figure_();
672                 }
673                 catch ( IOException e )
674                 {
675                     this.getLog().debug( "createCoberturaGraph exception = " + e.getMessage() );
676                 }
677             }
678         }
679         // else
680         // {
681         // sink.text("[" + bundle.getString("dashboard.report.generategraphs.disabled") + "]");
682         // sink.lineBreak();
683         // }
684     }
685 
686     public void createPmdSection( ResourceBundle bundle, Sink sink, PmdReportBean report )
687     {
688 
689         sink.section1();
690 
691         sink.sectionTitle2();
692         sink.anchor( "pmd" );
693         sink.anchor_();
694         if ( this.summary )
695         {
696             sink.link( "dashboard-report-details.html#pmd" );
697             sink.text( bundle.getString( "report.pmd.header" ) );
698             sink.link_();
699         }
700         else
701         {
702             sink.link( "./pmd.html" );
703             sink.text( bundle.getString( "report.pmd.header" ) );
704             sink.link_();
705         }
706 
707         sink.sectionTitle2_();
708         this.linkToTopPage( sink );
709         sink.lineBreak();
710         if ( this.isDBAvailable )
711         {
712             this.linkToHistoricPage( sink, "pmd" );
713         }
714         sink.section1_();
715         sink.lineBreak();
716         if ( report == null )
717         {
718             sink.text( "Error: Unable to read from PMD data file ." );
719         }
720         else
721         {
722             sink.table();
723             sink.tableRow();
724 
725             this.sinkHeader( sink, bundle.getString( "report.pmd.label.nbclasses" ) );
726 
727             this.sinkHeader( sink, bundle.getString( "report.pmd.label.nbviolations" ) );
728 
729             sink.tableRow_();
730 
731             sink.tableRow();
732 
733             this.sinkCell( sink, Integer.toString( report.getNbClasses() ) );
734 
735             this.sinkCell( sink, Integer.toString( report.getNbViolations() ) );
736 
737             sink.tableRow_();
738 
739             sink.table_();
740         }
741         sink.lineBreak();
742     }
743 
744     public void createCpdSection( ResourceBundle bundle, Sink sink, CpdReportBean report )
745     {
746 
747         sink.section1();
748 
749         sink.sectionTitle2();
750         sink.anchor( "cpd" );
751         sink.anchor_();
752         if ( this.summary )
753         {
754             sink.link( "dashboard-report-details.html#cpd" );
755             sink.text( bundle.getString( "report.cpd.header" ) );
756             sink.link_();
757         }
758         else
759         {
760             sink.link( "./cpd.html" );
761             sink.text( bundle.getString( "report.cpd.header" ) );
762             sink.link_();
763         }
764         sink.sectionTitle2_();
765         this.linkToTopPage( sink );
766         sink.lineBreak();
767         if ( this.isDBAvailable )
768         {
769             this.linkToHistoricPage( sink, "cpd" );
770         }
771         sink.section1_();
772         sink.lineBreak();
773         if ( report == null )
774         {
775             sink.text( "Error: Unable to read from CPD data file ." );
776         }
777         else
778         {
779             sink.table();
780             sink.tableRow();
781 
782             this.sinkHeader( sink, bundle.getString( "report.cpd.label.nbclasses" ) );
783 
784             this.sinkHeader( sink, bundle.getString( "report.cpd.label.nbduplicate" ) );
785 
786             sink.tableRow_();
787 
788             sink.tableRow();
789 
790             this.sinkCell( sink, Integer.toString( report.getNbClasses() ) );
791 
792             this.sinkCell( sink, Integer.toString( report.getNbDuplicate() ) );
793 
794             sink.tableRow_();
795 
796             sink.table_();
797         }
798         sink.lineBreak();
799     }
800 
801     public void createCheckStyleSection( ResourceBundle bundle, Sink sink, CheckstyleReportBean report )
802     {
803 
804         sink.section1();
805         sink.sectionTitle2();
806         sink.anchor( "checkstyle" );
807         sink.anchor_();
808         if ( this.summary )
809         {
810             sink.link( "dashboard-report-details.html#checkstyle" );
811             sink.text( bundle.getString( "report.checkstyle.header" ) );
812             sink.link_();
813         }
814         else
815         {
816             sink.link( "./checkstyle.html" );
817             sink.text( bundle.getString( "report.checkstyle.header" ) );
818             sink.link_();
819         }
820         sink.sectionTitle2_();
821         this.linkToTopPage( sink );
822         sink.lineBreak();
823         if ( this.isDBAvailable )
824         {
825             this.linkToHistoricPage( sink, "checkstyle" );
826         }
827         sink.section1_();
828         if ( report == null )
829         {
830             sink.text( "Error: Unable to read from checkstyle data file ." );
831         }
832         else
833         {
834             sink.table();
835 
836             sink.tableRow();
837             sink.tableHeaderCell();
838             sink.text( bundle.getString( "report.checkstyle.files" ) );
839             sink.tableHeaderCell_();
840 
841             sink.tableHeaderCell();
842             sink.text( bundle.getString( "report.checkstyle.column.total" ) );
843             sink.tableHeaderCell_();
844 
845             sink.tableHeaderCell();
846             sink.text( bundle.getString( "report.checkstyle.column.infos" ) );
847             sink.nonBreakingSpace();
848             this.iconInfo( sink );
849             sink.tableHeaderCell_();
850 
851             sink.tableHeaderCell();
852             sink.text( bundle.getString( "report.checkstyle.column.warnings" ) );
853             sink.nonBreakingSpace();
854             this.iconWarning( sink );
855             sink.tableHeaderCell_();
856 
857             sink.tableHeaderCell();
858             sink.text( bundle.getString( "report.checkstyle.column.errors" ) );
859             sink.nonBreakingSpace();
860             this.iconError( sink );
861             sink.tableHeaderCell_();
862             sink.tableRow_();
863 
864             sink.tableRow();
865 
866             this.sinkCell( sink, Integer.toString( report.getNbClasses() ) );
867             this.sinkCell( sink, Integer.toString( report.getNbTotal() ) );
868 
869             sink.tableCell();
870             sink.text( Integer.toString( report.getNbInfos() ) );
871             sinkInvertPercentGraphic( sink, report.getPercentInfos() );
872             sink.tableCell_();
873             sink.tableCell();
874             sink.text( Integer.toString( report.getNbWarnings() ) );
875             sinkInvertPercentGraphic( sink, report.getPercentWarnings() );
876             sink.tableCell_();
877             sink.tableCell();
878             sink.text( Integer.toString( report.getNbErrors() ) );
879             sinkInvertPercentGraphic( sink, report.getPercentErrors() );
880             sink.tableCell_();
881 
882             sink.tableRow_();
883             sink.table_();
884         }
885         sink.lineBreak();
886         if ( this.generateGraphs )
887         {
888             IChartRenderer chart =
889                 new PieChartRenderer( new CheckstylePieChartStrategy( bundle, this.mavenProject.getProjectName(),
890                                                                       report ),
891                                       DashBoardReportGenerator.SPECIFIC_WIDTH, ChartUtils.STANDARD_HEIGHT );
892             if ( !chart.isEmpty() )
893             {
894                 String filename = this.replaceForbiddenChar( this.mavenProject.getProjectName() );
895                 if ( this.summary )
896                 {
897                     filename += "_Summary_CheckStyle." + chart.getFileExtension();
898                 }
899                 else
900                 {
901                     filename += "_CheckStyle." + chart.getFileExtension();
902                 }
903                 filename = filename.replace( ' ', '_' );
904                 String filenameWithPath = this.getImagesPath() + "/" + filename;
905                 this.getLog().debug( "createCheckStyleGraph = " + filename );
906                 try
907                 {
908                     chart.saveToFile( filenameWithPath );
909                     String link = "images/" + filename;
910                     link = link.replace( ' ', '_' );
911                     sink.figure();
912                     sink.figureGraphics( link );
913                     sink.figure_();
914                 }
915                 catch ( IOException e )
916                 {
917                     this.getLog().debug( "createCheckStyleGraph exception = " + e.getMessage() );
918                 }
919             }
920 
921             // error management for Checkstyle Violations Chart. Fixes MOJO-679 .
922             // Written by <a href="mailto:srivollet@objectif-informatique.fr">Sylvain Rivollet</a>.
923 
924             IChartRenderer chartError =
925                 new PieChart3DRenderer(
926                                         new CheckstyleErrorsPieChartStrategy(
927                                                                               bundle,
928                                                                               this.mavenProject.getProjectName()
929                                                                                               + " "
930                                                                                               + bundle.getString( "chart.checkstyle.violations.title" ),
931                                                                               report ), ChartUtils.STANDARD_WIDTH,
932                                         ChartUtils.STANDARD_HEIGHT );
933             sink.lineBreak();
934             sink.lineBreak();
935 
936             if ( !chartError.isEmpty() )
937             {
938                 String filename = this.replaceForbiddenChar( this.mavenProject.getProjectName() );
939                 if ( this.summary )
940                 {
941                     filename += "_Summary_CheckStyle_Error." + chartError.getFileExtension();
942                 }
943                 else
944                 {
945                     filename += "_CheckStyle_Error." + chartError.getFileExtension();
946                 }
947                 filename = filename.replace( ' ', '_' );
948                 String filenameWithPath = this.getImagesPath() + "/" + filename;
949                 try
950                 {
951                     chartError.saveToFile( filenameWithPath );
952                     String link = "images/" + filename;
953                     link = link.replace( ' ', '_' );
954                     sink.figure();
955                     sink.figureGraphics( link );
956                     sink.figure_();
957                 }
958                 catch ( IOException e )
959                 {
960                     this.getLog().debug( "createCheckStyleGraphError exception = " + e.getMessage() );
961                 }
962             }
963         }
964         else
965         {
966 
967             sink.sectionTitle3();
968             sink.text( this.mavenProject.getProjectName() + " "
969                             + bundle.getString( "chart.checkstyle.violations.title" ) );
970             sink.sectionTitle3_();
971 
972             double percentVal = 0;
973             int nbItInfPercent = 0;
974             CheckstyleError error = new CheckstyleError();
975             List errorsUnSorted = report.getErrors();
976             Collections.sort( errorsUnSorted, new DescNbErrorCheckstyleComparator() );
977             Iterator iterator = errorsUnSorted.iterator();
978             int total = report.getNbTotal();
979 
980             sink.table();
981 
982             sink.tableRow();
983             sink.tableHeaderCell();
984             sink.text( "Violations" );
985             sink.tableHeaderCell_();
986 
987             sink.tableHeaderCell();
988             sink.text( "Rate" );
989             sink.tableHeaderCell_();
990 
991             sink.tableRow_();
992 
993             while ( iterator.hasNext() )
994             {
995                 error = (CheckstyleError) iterator.next();
996                 percentVal = (double) ( error.getNbIteration() * 1d / total );
997                 if ( percentVal > 0.01d )
998                 {
999                     sink.tableRow();
1000                     this.sinkCell( sink, error.getMessage() );
1001                     this.sinkCellInvertPercentGraphic( sink, percentVal, "checkstyle" );
1002                     sink.tableRow_();
1003                 }
1004                 else
1005                 {
1006                     nbItInfPercent += error.getNbIteration();
1007                 }
1008             }
1009 
1010             if ( nbItInfPercent > 0 )
1011             {
1012                 percentVal = (double) ( nbItInfPercent * 1d / total );
1013                 sink.tableRow();
1014                 this.sinkCell( sink, bundle.getString( "chart.checkstyle.violations.others.label" ) );
1015                 this.sinkCellInvertPercentGraphic( sink, percentVal, "checkstyle" );
1016                 sink.tableRow_();
1017             }
1018 
1019             sink.table_();
1020         }
1021 
1022     }
1023 
1024     public void createJDependSection( ResourceBundle bundle, Sink sink, JDependReportBean report )
1025     {
1026         this.getLog().debug( "createJDependSection creation." );
1027         sink.section1();
1028 
1029         sink.sectionTitle2();
1030         sink.anchor( "jdepend" );
1031         sink.anchor_();
1032         if ( this.summary )
1033         {
1034             sink.link( "dashboard-report-details.html#jdepend" );
1035             sink.text( "Top " + this.getNbExportedPackagesSummary() + " "
1036                             + bundle.getString( "report.xrefpackage.header" ) );
1037             sink.link_();
1038         }
1039         else
1040         {
1041             sink.link( "./jdepend-report.html" );
1042             sink.text( bundle.getString( "report.xrefpackage.header" ) );
1043             sink.link_();
1044         }
1045         sink.sectionTitle2_();
1046         this.linkToTopPage( sink );
1047         sink.lineBreak();
1048 
1049         sink.section1_();
1050         sink.lineBreak();
1051         if ( report == null )
1052         {
1053             sink.text( "Error: Unable to read from Jdepend data file ." );
1054         }
1055         else
1056         {
1057             double averageAC = report.getAverageAfferentCoupling();
1058 
1059             double calcul = ( Math.rint( averageAC * 1000 ) ) / 1000;
1060 
1061             sink.sectionTitle3();
1062             sink.text( bundle.getString( "report.xrefpackage.label.average" ) + " = " + calcul );
1063             sink.lineBreak();
1064             sink.text( " Nb Packages = " + report.getNbPackages() );
1065             sink.sectionTitle3_();
1066             sink.table();
1067             sink.tableRow();
1068 
1069             this.sinkHeader( sink, bundle.getString( "report.xrefpackage.label.package" ) );
1070 
1071             this.sinkHeader( sink, bundle.getString( "report.xrefpackage.label.ac" ) );
1072 
1073             this.sinkHeader( sink, bundle.getString( "report.xrefpackage.label.linecover" ) );
1074 
1075             this.sinkHeader( sink, bundle.getString( "report.xrefpackage.label.branchcover" ) );
1076 
1077             sink.tableRow_();
1078 
1079             List pack = report.getPackages();
1080             Iterator iter = pack.iterator();
1081             boolean threshold = false;
1082             int nbPack = 0;
1083             while ( iter.hasNext() )
1084             {
1085                 nbPack = nbPack + 1;
1086                 XRefPackageBean bean = (XRefPackageBean) iter.next();
1087                 Integer ac = bean.getAfferentCoupling();
1088                 if ( ac.doubleValue() <= averageAC && !threshold )
1089                 {
1090                     threshold = true;
1091                     sink.tableRow();
1092                     this.sinkCellBold( sink, bundle.getString( "report.xrefpackage.label.threshold" ) );
1093                     this.sinkCellBold( sink, String.valueOf( calcul ) );
1094                     // sinkHeader( sink, "" );
1095                     // sinkHeader( sink, "" );
1096                     sink.tableRow_();
1097                 }
1098                 sink.tableRow();
1099                 this.sinkCell( sink, bean.getPackageName() );
1100                 this.sinkCell( sink, ac.toString() );
1101                 // this.sinkCell(sink, getPercentValue(bean.getLineCoverRate()));
1102                 sinkCellPercentGraphic( sink, bean.getLineCoverRate(), "cobertura" );
1103                 // this.sinkCell(sink, getPercentValue(bean.getBranchCoverRate()));
1104                 sinkCellPercentGraphic( sink, bean.getBranchCoverRate(), "cobertura" );
1105                 sink.tableRow_();
1106                 if ( this.summary && nbPack >= this.getNbExportedPackagesSummary() )
1107                 {
1108                     break;
1109                 }
1110             }
1111 
1112             sink.table_();
1113         }
1114         sink.lineBreak();
1115     }
1116 
1117     public void createFindBugsSection( ResourceBundle bundle, Sink sink, FindBugsReportBean report )
1118     {
1119 
1120         sink.section1();
1121         sink.sectionTitle2();
1122         sink.anchor( "findbugs" );
1123         sink.anchor_();
1124         if ( this.summary )
1125         {
1126             sink.link( "dashboard-report-details.html#findbugs" );
1127             sink.text( bundle.getString( "report.findbugs.header" ) );
1128             sink.link_();
1129         }
1130         else
1131         {
1132             sink.link( "./findbugs.html" );
1133             sink.text( bundle.getString( "report.findbugs.header" ) );
1134             sink.link_();
1135         }
1136         sink.sectionTitle2_();
1137         this.linkToTopPage( sink );
1138         sink.lineBreak();
1139         if ( this.isDBAvailable )
1140         {
1141             this.linkToHistoricPage( sink, "findbugs" );
1142         }
1143         sink.section1_();
1144         if ( report == null )
1145         {
1146             sink.text( "Error: Unable to read from findbugs data file ." );
1147         }
1148         else
1149         {
1150             sink.table();
1151 
1152             sink.tableRow();
1153             sink.tableHeaderCell();
1154             sink.text( bundle.getString( "report.findbugs.label.nbclasses" ) );
1155             sink.tableHeaderCell_();
1156 
1157             sink.tableHeaderCell();
1158             sink.text( bundle.getString( "report.findbugs.label.nbbugs" ) );
1159             sink.tableHeaderCell_();
1160 
1161             sink.tableHeaderCell();
1162             sink.text( bundle.getString( "report.findbugs.label.nberrors" ) );
1163             sink.tableHeaderCell_();
1164 
1165             sink.tableHeaderCell();
1166             sink.text( bundle.getString( "report.findbugs.label.nbMissingClasses" ) );
1167             sink.tableHeaderCell_();
1168 
1169             sink.tableRow_();
1170 
1171             sink.tableRow();
1172 
1173             this.sinkCell( sink, Integer.toString( report.getNbClasses() ) );
1174             this.sinkCell( sink, Integer.toString( report.getNbBugs() ) );
1175             this.sinkCell( sink, Integer.toString( report.getNbErrors() ) );
1176             this.sinkCell( sink, Integer.toString( report.getNbMissingClasses() ) );
1177 
1178             sink.tableRow_();
1179 
1180             sink.table_();
1181         }
1182         sink.lineBreak();
1183         if ( this.generateGraphs )
1184         {
1185             IChartRenderer chartError =
1186                 new PieChart3DRenderer(
1187                                         new FindbugsCategoriesPieChartStrategy(
1188                                                                                 bundle,
1189                                                                                 this.mavenProject.getProjectName()
1190                                                                                                 + " "
1191                                                                                                 + bundle.getString( "chart.findbugs.bycategory.title" ),
1192                                                                                 report ), ChartUtils.STANDARD_WIDTH,
1193                                         ChartUtils.STANDARD_HEIGHT );
1194             sink.lineBreak();
1195             sink.lineBreak();
1196 
1197             if ( !chartError.isEmpty() )
1198             {
1199                 String filename = this.replaceForbiddenChar( this.mavenProject.getProjectName() );
1200                 if ( this.summary )
1201                 {
1202                     filename += "_Summary_Findbugs_Categories." + chartError.getFileExtension();
1203                 }
1204                 else
1205                 {
1206                     filename += "_Findbugs_Categories." + chartError.getFileExtension();
1207                 }
1208                 filename = filename.replace( ' ', '_' );
1209                 String filenameWithPath = this.getImagesPath() + "/" + filename;
1210                 try
1211                 {
1212                     chartError.saveToFile( filenameWithPath );
1213                     String link = "images/" + filename;
1214                     link = link.replace( ' ', '_' );
1215                     sink.figure();
1216                     sink.figureGraphics( link );
1217                     sink.figure_();
1218                 }
1219                 catch ( IOException e )
1220                 {
1221                     this.getLog().debug( "createFindbugsCategoriesGraphError exception = " + e.getMessage() );
1222                 }
1223             }
1224             sink.lineBreak();
1225             chartError =
1226                 new PieChart3DRenderer(
1227                                         new FindbugsPrioritiesPieChartStrategy(
1228                                                                                 bundle,
1229                                                                                 this.mavenProject.getProjectName()
1230                                                                                                 + " "
1231                                                                                                 + bundle.getString( "chart.findbugs.bypriority.title" ),
1232                                                                                 report ), ChartUtils.STANDARD_WIDTH,
1233                                         ChartUtils.STANDARD_HEIGHT );
1234             sink.lineBreak();
1235             sink.lineBreak();
1236 
1237             if ( !chartError.isEmpty() )
1238             {
1239                 String filename = this.replaceForbiddenChar( this.mavenProject.getProjectName() );
1240                 if ( this.summary )
1241                 {
1242                     filename += "_Summary_Findbugs_Priorities." + chartError.getFileExtension();
1243                 }
1244                 else
1245                 {
1246                     filename += "_Findbugs_Priorities." + chartError.getFileExtension();
1247                 }
1248                 filename = filename.replace( ' ', '_' );
1249                 String filenameWithPath = this.getImagesPath() + "/" + filename;
1250                 try
1251                 {
1252                     chartError.saveToFile( filenameWithPath );
1253                     String link = "images/" + filename;
1254                     link = link.replace( ' ', '_' );
1255                     sink.figure();
1256                     sink.figureGraphics( link );
1257                     sink.figure_();
1258                 }
1259                 catch ( IOException e )
1260                 {
1261                     this.getLog().debug( "createFindbugsPrioritiesGraphError exception = " + e.getMessage() );
1262                 }
1263             }
1264         }
1265         else
1266         {
1267             sink.sectionTitle3();
1268             sink.text( this.mavenProject.getProjectName() + " " + bundle.getString( "chart.findbugs.bycategory.title" ) );
1269             sink.sectionTitle3_();
1270             sink.table();
1271             sink.tableRow();
1272             sink.tableHeaderCell();
1273             sink.text( "Categories" );
1274             sink.tableHeaderCell_();
1275 
1276             sink.tableHeaderCell();
1277             sink.text( "Rate" );
1278             sink.tableHeaderCell_();
1279 
1280             sink.tableRow_();
1281 
1282             Map categories = report.getCategories();
1283             Iterator iterator = categories.keySet().iterator();
1284             while ( iterator.hasNext() )
1285             {
1286                 String category = (String) iterator.next();
1287                 Integer value = (Integer) categories.get( category );
1288                 double percentVal = value.intValue() / (double) report.getNbBugs();
1289 
1290                 sink.tableRow();
1291                 this.sinkCell( sink, category );
1292                 this.sinkCellInvertPercentGraphic( sink, percentVal, "findbugs" );
1293                 sink.tableRow_();
1294             }
1295             sink.table_();
1296             sink.lineBreak();
1297 
1298             sink.sectionTitle3();
1299             sink.text( this.mavenProject.getProjectName() + " " + bundle.getString( "chart.findbugs.bypriority.title" ) );
1300             sink.sectionTitle3_();
1301             sink.table();
1302             sink.tableRow();
1303             sink.tableHeaderCell();
1304             sink.text( "Priorities" );
1305             sink.tableHeaderCell_();
1306 
1307             sink.tableHeaderCell();
1308             sink.text( "Rate" );
1309             sink.tableHeaderCell_();
1310 
1311             sink.tableRow_();
1312 
1313             Map priorities = report.getPriorities();
1314             Iterator iteratorP = priorities.keySet().iterator();
1315             while ( iteratorP.hasNext() )
1316             {
1317                 String priority = (String) iteratorP.next();
1318                 Integer value = (Integer) priorities.get( priority );
1319                 double percentVal = value.intValue() / (double) report.getNbBugs();
1320 
1321                 sink.tableRow();
1322                 this.sinkCell( sink, priority );
1323                 this.sinkCellInvertPercentGraphic( sink, percentVal, "findbugs" );
1324                 sink.tableRow_();
1325             }
1326             sink.table_();
1327         }
1328     }
1329 
1330     public void createTaglistSection( ResourceBundle bundle, Sink sink, TagListReportBean report )
1331     {
1332 
1333         sink.section1();
1334         sink.sectionTitle2();
1335         sink.anchor( "taglist" );
1336         sink.anchor_();
1337         if ( this.summary )
1338         {
1339             sink.link( "dashboard-report-details.html#taglist" );
1340             sink.text( bundle.getString( "report.taglist.header" ) );
1341             sink.link_();
1342         }
1343         else
1344         {
1345             sink.link( "./taglist.html" );
1346             sink.text( bundle.getString( "report.taglist.header" ) );
1347             sink.link_();
1348         }
1349         sink.sectionTitle2_();
1350         this.linkToTopPage( sink );
1351         sink.lineBreak();
1352         if ( this.isDBAvailable )
1353         {
1354             this.linkToHistoricPage( sink, "taglist" );
1355         }
1356         sink.section1_();
1357 
1358         if ( report == null )
1359         {
1360             sink.text( "Error: Unable to read from taglist data file ." );
1361         }
1362         else
1363         {
1364             sink.table();
1365 
1366             sink.tableRow();
1367             sink.tableHeaderCell();
1368             sink.text( bundle.getString( "report.taglist.column.tags" ) );
1369             sink.tableHeaderCell_();
1370 
1371             sink.tableHeaderCell();
1372             sink.text( bundle.getString( "report.taglist.column.nboccurs" ) );
1373             sink.tableHeaderCell_();
1374 
1375             sink.tableRow_();
1376 
1377             for ( Iterator ite = report.getTags().entrySet().iterator(); ite.hasNext(); )
1378             {
1379                 sink.tableRow();
1380                 Map.Entry entry = (Map.Entry) ite.next();
1381                 this.sinkCell( sink, (String) entry.getKey() );
1382                 this.sinkCell( sink, ( (Integer) entry.getValue() ).toString() );
1383                 sink.tableRow_();
1384 
1385             }
1386 
1387             sink.tableRow();
1388             sink.tableHeaderCell();
1389             sink.text( "Total" );
1390             sink.tableHeaderCell_();
1391 
1392             sink.tableHeaderCell();
1393             sink.text( Integer.toString( report.getNbTotal() ) );
1394             sink.tableHeaderCell_();
1395             sink.tableRow_();
1396             sink.tableRow();
1397             sink.tableHeaderCell();
1398             sink.text( bundle.getString( "report.taglist.label.nbclasses" ) );
1399             sink.tableHeaderCell_();
1400 
1401             sink.tableHeaderCell();
1402             sink.text( Integer.toString( report.getNbClasses() ) );
1403             sink.tableHeaderCell_();
1404             sink.tableRow_();
1405 
1406             sink.table_();
1407 
1408         }
1409         sink.lineBreak();
1410         if ( this.generateGraphs )
1411         {
1412             IChartRenderer chart =
1413                 new PieChart3DRenderer( new TaglistPieChartStrategy( bundle, this.mavenProject.getProjectName() + " "
1414                                 + bundle.getString( "chart.taglist.bytags.title" ), report ),
1415                                         DashBoardReportGenerator.SPECIFIC_WIDTH, ChartUtils.STANDARD_HEIGHT );
1416             if ( !chart.isEmpty() )
1417             {
1418                 String filename = this.replaceForbiddenChar( this.mavenProject.getProjectName() );
1419                 if ( this.summary )
1420                 {
1421                     filename += "_Summary_Taglist." + chart.getFileExtension();
1422                 }
1423                 else
1424                 {
1425                     filename += "_Taglist." + chart.getFileExtension();
1426                 }
1427                 filename = filename.replace( ' ', '_' );
1428                 String filenameWithPath = this.getImagesPath() + "/" + filename;
1429                 this.getLog().debug( "createTaglistGraph = " + filename );
1430                 try
1431                 {
1432                     chart.saveToFile( filenameWithPath );
1433                     String link = "images/" + filename;
1434                     link = link.replace( ' ', '_' );
1435                     sink.figure();
1436                     sink.figureGraphics( link );
1437                     sink.figure_();
1438                 }
1439                 catch ( IOException e )
1440                 {
1441                     this.getLog().debug( "createTaglistGraph exception = " + e.getMessage() );
1442                 }
1443             }
1444         }
1445         // else
1446         // {
1447         // sink.text("[" + bundle.getString("dashboard.report.generategraphs.disabled") + "]");
1448         // sink.lineBreak();
1449         // }
1450     }
1451 }