Coverage Report - org.apache.maven.plugin.checkstyle.CheckstyleReportGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
CheckstyleReportGenerator
86%
353/411
60%
64/106
0
 
 1  
 package org.apache.maven.plugin.checkstyle;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.File;
 23  
 import java.util.ArrayList;
 24  
 import java.util.Arrays;
 25  
 import java.util.Collection;
 26  
 import java.util.Collections;
 27  
 import java.util.Iterator;
 28  
 import java.util.List;
 29  
 import java.util.ResourceBundle;
 30  
 
 31  
 import org.apache.maven.doxia.sink.Sink;
 32  
 import org.apache.maven.doxia.tools.SiteTool;
 33  
 import org.apache.maven.plugin.logging.Log;
 34  
 import org.apache.maven.plugin.logging.SystemStreamLog;
 35  
 import org.codehaus.plexus.util.StringUtils;
 36  
 
 37  
 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
 38  
 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
 39  
 import com.puppycrawl.tools.checkstyle.api.Configuration;
 40  
 import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
 41  
 
 42  
 /**
 43  
  * Generate a report based on CheckstyleResults.
 44  
  *
 45  
  * @version $Id$
 46  
  */
 47  
 public class CheckstyleReportGenerator
 48  
 {
 49  
     private Log log;
 50  
 
 51  
     private File basedir;
 52  
 
 53  
     private ResourceBundle bundle;
 54  
 
 55  
     private Sink sink;
 56  
 
 57  
     private SeverityLevel severityLevel;
 58  
 
 59  
     private Configuration checkstyleConfig;
 60  
 
 61  
     private boolean enableRulesSummary;
 62  
 
 63  
     private boolean enableSeveritySummary;
 64  
 
 65  
     private boolean enableFilesSummary;
 66  
 
 67  
     private boolean enableRSS;
 68  
 
 69  
     private SiteTool siteTool;
 70  
 
 71  
     private String xrefLocation;
 72  
 
 73  
     public CheckstyleReportGenerator( Sink sink, ResourceBundle bundle, File basedir, SiteTool siteTool )
 74  28
     {
 75  28
         this.bundle = bundle;
 76  
 
 77  28
         this.sink = sink;
 78  
 
 79  28
         this.basedir = basedir;
 80  
 
 81  28
         this.siteTool = siteTool;
 82  
 
 83  28
         this.enableRulesSummary = true;
 84  28
         this.enableSeveritySummary = true;
 85  28
         this.enableFilesSummary = true;
 86  28
         this.enableRSS = true;
 87  28
     }
 88  
 
 89  
     public Log getLog()
 90  
     {
 91  48
         if ( this.log == null )
 92  
         {
 93  0
             this.log = new SystemStreamLog();
 94  
         }
 95  48
         return this.log;
 96  
     }
 97  
 
 98  
     public void setLog( Log log )
 99  
     {
 100  28
         this.log = log;
 101  28
     }
 102  
 
 103  
     private String getTitle()
 104  
     {
 105  
         String title;
 106  
 
 107  56
         if ( getSeverityLevel() == null )
 108  
         {
 109  56
             title = bundle.getString( "report.checkstyle.title" );
 110  
         }
 111  
         else
 112  
         {
 113  0
             title = bundle.getString( "report.checkstyle.severity_title" ) + severityLevel.getName();
 114  
         }
 115  
 
 116  56
         return title;
 117  
     }
 118  
 
 119  
     public void generateReport( CheckstyleResults results )
 120  
     {
 121  28
         doHeading();
 122  
 
 123  28
         if ( getSeverityLevel() == null )
 124  
         {
 125  28
             if ( enableSeveritySummary )
 126  
             {
 127  24
                 doSeveritySummary( results );
 128  
             }
 129  
 
 130  28
             if ( enableFilesSummary )
 131  
             {
 132  24
                 doFilesSummary( results );
 133  
             }
 134  
 
 135  28
             if ( enableRulesSummary )
 136  
             {
 137  24
                 doRulesSummary( results );
 138  
             }
 139  
         }
 140  
 
 141  28
         doDetails( results );
 142  28
         sink.body_();
 143  28
         sink.flush();
 144  28
         sink.close();
 145  28
     }
 146  
 
 147  
     private void doHeading()
 148  
     {
 149  28
         sink.head();
 150  28
         sink.title();
 151  28
         sink.text( getTitle() );
 152  28
         sink.title_();
 153  28
         sink.head_();
 154  
 
 155  28
         sink.body();
 156  
 
 157  28
         sink.section1();
 158  28
         sink.sectionTitle1();
 159  28
         sink.text( getTitle() );
 160  28
         sink.sectionTitle1_();
 161  
 
 162  28
         sink.paragraph();
 163  28
         sink.text( bundle.getString( "report.checkstyle.checkstylelink" ) + " " );
 164  28
         sink.link( "http://checkstyle.sourceforge.net/" );
 165  28
         sink.text( "Checkstyle" );
 166  28
         sink.link_();
 167  28
         sink.text( "." );
 168  
 
 169  28
         if ( enableRSS )
 170  
         {
 171  28
             sink.nonBreakingSpace();
 172  28
             sink.link( "checkstyle.rss" );
 173  28
             sink.figure();
 174  28
             sink.figureCaption();
 175  28
             sink.text( "rss feed" );
 176  28
             sink.figureCaption_();
 177  28
             sink.figureGraphics( "images/rss.png" );
 178  28
             sink.figure_();
 179  28
             sink.link_();
 180  
         }
 181  
 
 182  28
         sink.paragraph_();
 183  28
         sink.section1_();
 184  28
     }
 185  
 
 186  
     private void iconSeverity( String level )
 187  
     {
 188  1452
         if ( SeverityLevel.INFO.getName().equalsIgnoreCase( level ) )
 189  
         {
 190  4
             iconInfo();
 191  
         }
 192  1448
         else if ( SeverityLevel.WARNING.getName().equalsIgnoreCase( level ) )
 193  
         {
 194  8
             iconWarning();
 195  
         }
 196  1440
         else if ( SeverityLevel.ERROR.getName().equalsIgnoreCase( level ) )
 197  
         {
 198  1440
             iconError();
 199  
         }
 200  1452
     }
 201  
 
 202  
     private void iconInfo()
 203  
     {
 204  52
         sink.figure();
 205  52
         sink.figureCaption();
 206  52
         sink.text( bundle.getString( "report.checkstyle.infos" ) );
 207  52
         sink.figureCaption_();
 208  52
         sink.figureGraphics( "images/icon_info_sml.gif" );
 209  52
         sink.figure_();
 210  52
     }
 211  
 
 212  
     private void iconWarning()
 213  
     {
 214  64
         sink.figure();
 215  64
         sink.figureCaption();
 216  64
         sink.text( bundle.getString( "report.checkstyle.warnings" ) );
 217  64
         sink.figureCaption_();
 218  64
         sink.figureGraphics( "images/icon_warning_sml.gif" );
 219  64
         sink.figure_();
 220  64
     }
 221  
 
 222  
     private void iconError()
 223  
     {
 224  1628
         sink.figure();
 225  1628
         sink.figureCaption();
 226  1628
         sink.text( bundle.getString( "report.checkstyle.errors" ) );
 227  1628
         sink.figureCaption_();
 228  1628
         sink.figureGraphics( "images/icon_error_sml.gif" );
 229  1628
         sink.figure_();
 230  1628
     }
 231  
 
 232  
     /**
 233  
      * Get the value of the specified attribute from the Checkstyle configuration.
 234  
      * If parentConfigurations is non-null and non-empty, the parent
 235  
      * configurations are searched if the attribute cannot be found in the
 236  
      * current configuration. If the attribute is still not found, the
 237  
      * specified default value will be returned.
 238  
      *
 239  
      * @param config The current Checkstyle configuration
 240  
      * @param parentConfigurations The configurations for the parents of the current configuration
 241  
      * @param attributeName The name of the attribute
 242  
      * @param defaultValue The default value to use if the attribute cannot be found in any configuration
 243  
      * @return The value of the specified attribute
 244  
      */
 245  
     private String getConfigAttribute( Configuration config, List<Configuration> parentConfigurations,
 246  
                                        String attributeName, String defaultValue )
 247  
     {
 248  
         String ret;
 249  
         try
 250  
         {
 251  7252
             ret = config.getAttribute( attributeName );
 252  
         }
 253  7060
         catch ( CheckstyleException e )
 254  
         {
 255  
             // Try to find the attribute in a parent, if there are any
 256  7060
             if ( parentConfigurations != null && !parentConfigurations.isEmpty() )
 257  
             {
 258  2748
                 Configuration parentConfiguration = parentConfigurations.get( parentConfigurations.size() - 1 );
 259  2748
                 List<Configuration> newParentConfigurations = new ArrayList<Configuration>( parentConfigurations );
 260  
                 // Remove the last parent
 261  2748
                 newParentConfigurations.remove( parentConfiguration );
 262  2748
                 ret = getConfigAttribute( parentConfiguration, newParentConfigurations, attributeName, defaultValue );
 263  2748
             }
 264  
             else
 265  
             {
 266  4312
                 ret = defaultValue;
 267  
             }
 268  192
         }
 269  7252
         return ret;
 270  
     }
 271  
 
 272  
     /**
 273  
      * Create the rules summary section of the report.
 274  
      *
 275  
      * @param results The results to summarize
 276  
      */
 277  
     private void doRulesSummary( CheckstyleResults results )
 278  
     {
 279  24
         if ( checkstyleConfig == null )
 280  
         {
 281  0
             return;
 282  
         }
 283  
 
 284  24
         sink.section1();
 285  24
         sink.sectionTitle1();
 286  24
         sink.text( bundle.getString( "report.checkstyle.rules" ) );
 287  24
         sink.sectionTitle1_();
 288  
 
 289  24
         sink.table();
 290  
 
 291  24
         sink.tableRow();
 292  24
         sink.tableHeaderCell();
 293  24
         sink.text( bundle.getString( "report.checkstyle.rules" ) );
 294  24
         sink.tableHeaderCell_();
 295  
 
 296  24
         sink.tableHeaderCell();
 297  24
         sink.text( bundle.getString( "report.checkstyle.violations" ) );
 298  24
         sink.tableHeaderCell_();
 299  
 
 300  24
         sink.tableHeaderCell();
 301  24
         sink.text( bundle.getString( "report.checkstyle.column.severity" ) );
 302  24
         sink.tableHeaderCell_();
 303  24
         sink.tableRow_();
 304  
 
 305  
         // Top level should be the checker.
 306  24
         if ( "checker".equalsIgnoreCase( checkstyleConfig.getName() ) )
 307  
         {
 308  24
             doRuleChildren( checkstyleConfig, null, results );
 309  
         }
 310  
         else
 311  
         {
 312  0
             sink.tableRow();
 313  0
             sink.tableCell();
 314  0
             sink.text( bundle.getString( "report.checkstyle.norule" ) );
 315  0
             sink.tableCell_();
 316  0
             sink.tableRow_();
 317  
         }
 318  
 
 319  24
         sink.table_();
 320  
 
 321  24
         sink.section1_();
 322  24
     }
 323  
 
 324  
     /**
 325  
      * Create a summary for each Checkstyle rule.
 326  
      *
 327  
      * @param configuration The Checkstyle configuration
 328  
      * @param parentConfigurations A List of configurations for the chain of parents to the current configuration
 329  
      * @param results The results to summarize
 330  
      */
 331  
     private void doRuleChildren( Configuration configuration, List<Configuration> parentConfigurations,
 332  
                                  CheckstyleResults results )
 333  
     {
 334  
         // Remember the chain of parent configurations
 335  48
         if ( parentConfigurations == null )
 336  
         {
 337  24
             parentConfigurations = new ArrayList<Configuration>();
 338  
         }
 339  
         // The "oldest" parent will be first in the list
 340  48
         parentConfigurations.add( configuration );
 341  
 
 342  48
         if ( getLog().isDebugEnabled() )
 343  
         {
 344  
             // Log the parent configuration path
 345  0
             StringBuffer parentPath = new StringBuffer();
 346  0
             for ( Iterator<Configuration> iterator = parentConfigurations.iterator(); iterator.hasNext(); )
 347  
             {
 348  0
                 Configuration parentConfiguration = iterator.next();
 349  0
                 parentPath.append( parentConfiguration.getName() );
 350  0
                 if ( iterator.hasNext() )
 351  
                 {
 352  0
                     parentPath.append( " --> " );
 353  
                 }
 354  0
             }
 355  0
             if ( parentPath.length() > 0 )
 356  
             {
 357  0
                 getLog().debug( "Parent Configuration Path: " + parentPath.toString() );
 358  
             }
 359  
         }
 360  
 
 361  48
         Configuration configChildren[] = configuration.getChildren();
 362  1524
         for ( int cci = 0; cci < configChildren.length; cci++ )
 363  
         {
 364  1476
             String ruleName = configChildren[cci].getName();
 365  
 
 366  1476
             if ( "TreeWalker".equals( ruleName ) )
 367  
             {
 368  
                 // special sub-case
 369  24
                 doRuleChildren( configChildren[cci], parentConfigurations, results );
 370  
             }
 371  
             else
 372  
             {
 373  1452
                 doRuleRow( configChildren[cci], parentConfigurations, ruleName, results );
 374  
             }
 375  
         }
 376  48
     }
 377  
 
 378  
     /**
 379  
      * Create a summary for one Checkstyle rule.
 380  
      *
 381  
      * @param checkerConfig Configuration for the Checkstyle rule
 382  
      * @param parentConfigurations Configurations for the parents of this rule
 383  
      * @param ruleName The name of the rule, for example "JavadocMethod"
 384  
      * @param results The results to summarize
 385  
      */
 386  
     private void doRuleRow( Configuration checkerConfig, List<Configuration> parentConfigurations, String ruleName,
 387  
                             CheckstyleResults results )
 388  
     {
 389  1452
         sink.tableRow();
 390  1452
         sink.tableCell();
 391  1452
         sink.text( ruleName );
 392  
 
 393  1452
         List<String> attribnames = new ArrayList<String>( Arrays.asList( checkerConfig.getAttributeNames() ) );
 394  1452
         attribnames.remove( "severity" ); // special value (deserves unique column)
 395  1452
         if ( !attribnames.isEmpty() )
 396  
         {
 397  116
             sink.list();
 398  116
             for ( String name : attribnames )
 399  
             {
 400  148
                 sink.listItem();
 401  
 
 402  148
                 sink.bold();
 403  148
                 sink.text( name );
 404  148
                 sink.bold_();
 405  
 
 406  148
                 String value = getConfigAttribute( checkerConfig, null, name, "" );
 407  
                 // special case, Header.header and RegexpHeader.header
 408  148
                 if ( "header".equals( name ) && ( "Header".equals( ruleName ) || "RegexpHeader".equals( ruleName ) ) )
 409  
                 {
 410  0
                     List<String> lines = stringSplit( value, "\\n" );
 411  0
                     int linenum = 1;
 412  0
                     for ( String line : lines )
 413  
                     {
 414  0
                         sink.lineBreak();
 415  0
                         sink.rawText( "<span style=\"color: gray\">" );
 416  0
                         sink.text( linenum + ":" );
 417  0
                         sink.rawText( "</span>" );
 418  0
                         sink.nonBreakingSpace();
 419  0
                         sink.monospaced();
 420  0
                         sink.text( line );
 421  0
                         sink.monospaced_();
 422  0
                         linenum++;
 423  
                     }
 424  0
                 }
 425  148
                 else if ( "headerFile".equals( name ) && "RegexpHeader".equals( ruleName ) )
 426  
                 {
 427  4
                     sink.text( ": " );
 428  4
                     sink.monospaced();
 429  4
                     sink.text( "\"" );
 430  4
                     if ( basedir != null )
 431  
                     {
 432  
                         // Make the headerFile value relative to ${basedir}
 433  4
                         String path = siteTool.getRelativePath( value, basedir.getAbsolutePath() );
 434  4
                         sink.text( path.replace( '\\', '/' ) );
 435  4
                     }
 436  
                     else
 437  
                     {
 438  0
                         sink.text( value );
 439  
                     }
 440  4
                     sink.text( "\"" );
 441  4
                     sink.monospaced_();
 442  
                 }
 443  
                 else
 444  
                 {
 445  144
                     sink.text( ": " );
 446  144
                     sink.monospaced();
 447  144
                     sink.text( "\"" );
 448  144
                     sink.text( value );
 449  144
                     sink.text( "\"" );
 450  144
                     sink.monospaced_();
 451  
                 }
 452  148
                 sink.listItem_();
 453  148
             }
 454  116
             sink.list_();
 455  
         }
 456  
 
 457  1452
         sink.tableCell_();
 458  
 
 459  1452
         sink.tableCell();
 460  1452
         String fixedmessage = getConfigAttribute( checkerConfig, null, "message", null );
 461  
         // Grab the severity from the rule configuration, use null as default value
 462  1452
         String configSeverity = getConfigAttribute( checkerConfig, null, "severity", null );
 463  1452
         sink.text( countRuleViolation( results.getFiles().values(), ruleName, fixedmessage,
 464  
                                        configSeverity ) );
 465  1452
         sink.tableCell_();
 466  
 
 467  1452
         sink.tableCell();
 468  
         // Grab the severity from the rule configuration, this time use error as default value
 469  
         // Also pass along all parent configurations, so that we can try to find the severity there
 470  1452
         configSeverity = getConfigAttribute( checkerConfig, parentConfigurations, "severity", "error" );
 471  1452
         iconSeverity( configSeverity );
 472  1452
         sink.nonBreakingSpace();
 473  1452
         sink.text( StringUtils.capitalise( configSeverity ) );
 474  1452
         sink.tableCell_();
 475  
 
 476  1452
         sink.tableRow_();
 477  1452
     }
 478  
 
 479  
     /**
 480  
      * Splits a string against a delim consisting of a string (not a single character).
 481  
      *
 482  
      * @param input
 483  
      * @param delim
 484  
      * @return
 485  
      */
 486  
     private List<String> stringSplit( String input, String delim )
 487  
     {
 488  0
         List<String> ret = new ArrayList<String>();
 489  
 
 490  0
         int delimLen = delim.length();
 491  0
         int offset = 0;
 492  0
         int lastOffset = 0;
 493  
         String line;
 494  
 
 495  0
         while ( ( offset = input.indexOf( delim, offset ) ) >= 0 )
 496  
         {
 497  0
             line = input.substring( lastOffset, offset );
 498  0
             ret.add( line );
 499  0
             offset += delimLen;
 500  0
             lastOffset = offset;
 501  
         }
 502  
 
 503  0
         line = input.substring( lastOffset );
 504  0
         ret.add( line );
 505  
 
 506  0
         return ret;
 507  
     }
 508  
 
 509  
     /**
 510  
      * Count the number of violations for the given rule.
 511  
      *
 512  
      * @param files A collection over the set of files that has violations
 513  
      * @param ruleName The name of the rule
 514  
      * @param message A message that, if it's not null, will be matched to the message from the violation
 515  
      * @param severity A severity that, if it's not null, will be matched to the severity from the violation
 516  
      * @return The number of rule violations
 517  
      */
 518  
     private String countRuleViolation( Collection<List<AuditEvent>> files, String ruleName, String message,
 519  
                                        String severity )
 520  
     {
 521  1452
         long count = 0;
 522  
 
 523  1452
         for ( List<AuditEvent> errors : files )
 524  
         {
 525  1452
             for ( AuditEvent event : errors )
 526  
             {
 527  7644
                 String eventSrcName = event.getSourceName();
 528  7644
                 if ( eventSrcName != null
 529  
                         && ( eventSrcName.endsWith( ruleName )
 530  
                         || eventSrcName.endsWith( ruleName + "Check" ) ) )
 531  
                 {
 532  
                     // check message too, for those that have a specific one.
 533  
                     // like GenericIllegalRegexp and Regexp
 534  128
                     if ( message != null )
 535  
                     {
 536  
                         // event.getMessage() uses java.text.MessageFormat in its implementation.
 537  
                         // Read MessageFormat Javadoc about single quote:
 538  
                         // http://java.sun.com/j2se/1.4.2/docs/api/java/text/MessageFormat.html
 539  0
                         String msgWithoutSingleQuote = StringUtils.replace( message, "'", "" );
 540  0
                         if ( message.equals( event.getMessage() )
 541  
                             || msgWithoutSingleQuote.equals( event.getMessage() ) )
 542  
                         {
 543  0
                             count++;
 544  
                         }
 545  0
                     }
 546  
                     // Check the severity. This helps to distinguish between
 547  
                     // different configurations for the same rule, where each
 548  
                     // configuration has a different severity, like JavadocMetod.
 549  
                     // See also http://jira.codehaus.org/browse/MCHECKSTYLE-41
 550  128
                     else if ( severity != null )
 551  
                     {
 552  8
                         if ( severity.equals( event.getSeverityLevel().getName() ) )
 553  
                         {
 554  8
                             count++;
 555  
                         }
 556  
                     }
 557  
                     else
 558  
                     {
 559  120
                         count++;
 560  
                     }
 561  
                 }
 562  7644
             }
 563  
         }
 564  1452
         return String.valueOf( count );
 565  
     }
 566  
 
 567  
     private void doSeveritySummary( CheckstyleResults results )
 568  
     {
 569  24
         sink.section1();
 570  24
         sink.sectionTitle1();
 571  24
         sink.text( bundle.getString( "report.checkstyle.summary" ) );
 572  24
         sink.sectionTitle1_();
 573  
 
 574  24
         sink.table();
 575  
 
 576  24
         sink.tableRow();
 577  24
         sink.tableHeaderCell();
 578  24
         sink.text( bundle.getString( "report.checkstyle.files" ) );
 579  24
         sink.tableHeaderCell_();
 580  
 
 581  24
         sink.tableHeaderCell();
 582  24
         sink.text( bundle.getString( "report.checkstyle.infos" ) );
 583  24
         sink.nonBreakingSpace();
 584  24
         iconInfo();
 585  24
         sink.tableHeaderCell_();
 586  
 
 587  24
         sink.tableHeaderCell();
 588  24
         sink.text( bundle.getString( "report.checkstyle.warnings" ) );
 589  24
         sink.nonBreakingSpace();
 590  24
         iconWarning();
 591  24
         sink.tableHeaderCell_();
 592  
 
 593  24
         sink.tableHeaderCell();
 594  24
         sink.text( bundle.getString( "report.checkstyle.errors" ) );
 595  24
         sink.nonBreakingSpace();
 596  24
         iconError();
 597  24
         sink.tableHeaderCell_();
 598  24
         sink.tableRow_();
 599  
 
 600  24
         sink.tableRow();
 601  24
         sink.tableCell();
 602  24
         sink.text( String.valueOf( results.getFileCount() ) );
 603  24
         sink.tableCell_();
 604  24
         sink.tableCell();
 605  24
         sink.text( String.valueOf( results.getSeverityCount( SeverityLevel.INFO ) ) );
 606  24
         sink.tableCell_();
 607  24
         sink.tableCell();
 608  24
         sink.text( String.valueOf( results.getSeverityCount( SeverityLevel.WARNING ) ) );
 609  24
         sink.tableCell_();
 610  24
         sink.tableCell();
 611  24
         sink.text( String.valueOf( results.getSeverityCount( SeverityLevel.ERROR ) ) );
 612  24
         sink.tableCell_();
 613  24
         sink.tableRow_();
 614  
 
 615  24
         sink.table_();
 616  
 
 617  24
         sink.section1_();
 618  24
     }
 619  
 
 620  
     private void doFilesSummary( CheckstyleResults results )
 621  
     {
 622  24
         sink.section1();
 623  24
         sink.sectionTitle1();
 624  24
         sink.text( bundle.getString( "report.checkstyle.files" ) );
 625  24
         sink.sectionTitle1_();
 626  
 
 627  24
         sink.table();
 628  
 
 629  24
         sink.tableRow();
 630  24
         sink.tableHeaderCell();
 631  24
         sink.text( bundle.getString( "report.checkstyle.files" ) );
 632  24
         sink.tableHeaderCell_();
 633  24
         sink.tableHeaderCell();
 634  24
         sink.text( bundle.getString( "report.checkstyle.infos.abbrev" ) );
 635  24
         sink.nonBreakingSpace();
 636  24
         iconInfo();
 637  24
         sink.tableHeaderCell_();
 638  24
         sink.tableHeaderCell();
 639  24
         sink.text( bundle.getString( "report.checkstyle.warnings.abbrev" ) );
 640  24
         sink.nonBreakingSpace();
 641  24
         iconWarning();
 642  24
         sink.tableHeaderCell_();
 643  24
         sink.tableHeaderCell();
 644  24
         sink.text( bundle.getString( "report.checkstyle.errors.abbrev" ) );
 645  24
         sink.nonBreakingSpace();
 646  24
         iconError();
 647  24
         sink.tableHeaderCell_();
 648  24
         sink.tableRow_();
 649  
 
 650  
         // Sort the files before writing them to the report
 651  24
         List<String> fileList = new ArrayList<String>( results.getFiles().keySet() );
 652  24
         Collections.sort( fileList );
 653  
 
 654  24
         for ( String filename : fileList )
 655  
         {
 656  24
             List<AuditEvent> violations = results.getFileViolations( filename );
 657  24
             if ( violations.isEmpty() )
 658  
             {
 659  
                 // skip files without violations
 660  0
                 continue;
 661  
             }
 662  
 
 663  24
             sink.tableRow();
 664  
 
 665  24
             sink.tableCell();
 666  24
             sink.link( "#" + filename.replace( '/', '.' ) );
 667  24
             sink.text( filename );
 668  24
             sink.link_();
 669  24
             sink.tableCell_();
 670  
 
 671  24
             sink.tableCell();
 672  24
             sink.text( String.valueOf( results.getSeverityCount( violations, SeverityLevel.INFO ) ) );
 673  24
             sink.tableCell_();
 674  
 
 675  24
             sink.tableCell();
 676  24
             sink.text( String.valueOf( results.getSeverityCount( violations, SeverityLevel.WARNING ) ) );
 677  24
             sink.tableCell_();
 678  
 
 679  24
             sink.tableCell();
 680  24
             sink.text( String.valueOf( results.getSeverityCount( violations, SeverityLevel.ERROR ) ) );
 681  24
             sink.tableCell_();
 682  
 
 683  24
             sink.tableRow_();
 684  24
         }
 685  
 
 686  24
         sink.table_();
 687  24
         sink.section1_();
 688  24
     }
 689  
 
 690  
     private void doDetails( CheckstyleResults results )
 691  
     {
 692  
 
 693  28
         sink.section1();
 694  28
         sink.sectionTitle1();
 695  28
         sink.text( bundle.getString( "report.checkstyle.details" ) );
 696  28
         sink.sectionTitle1_();
 697  
 
 698  
         // Sort the files before writing their details to the report
 699  28
         List<String> fileList = new ArrayList<String>( results.getFiles().keySet() );
 700  28
         Collections.sort( fileList );
 701  
 
 702  28
         for ( String file : fileList )
 703  
         {
 704  28
             List<AuditEvent> violations = results.getFileViolations( file );
 705  
 
 706  28
             if ( violations.isEmpty() )
 707  
             {
 708  
                 // skip files without violations
 709  0
                 continue;
 710  
             }
 711  
 
 712  28
             sink.section2();
 713  28
             sink.sectionTitle2();
 714  28
             sink.text( file );
 715  28
             sink.sectionTitle2_();
 716  
 
 717  28
             sink.anchor( file.replace( '/', '.' ) );
 718  28
             sink.anchor_();
 719  
 
 720  28
             sink.table();
 721  28
             sink.tableRow();
 722  28
             sink.tableHeaderCell();
 723  28
             sink.text( bundle.getString( "report.checkstyle.column.violation" ) );
 724  28
             sink.tableHeaderCell_();
 725  28
             sink.tableHeaderCell();
 726  28
             sink.text( bundle.getString( "report.checkstyle.column.message" ) );
 727  28
             sink.tableHeaderCell_();
 728  28
             sink.tableHeaderCell();
 729  28
             sink.text( bundle.getString( "report.checkstyle.column.line" ) );
 730  28
             sink.tableHeaderCell_();
 731  28
             sink.tableRow_();
 732  
 
 733  28
             doFileEvents( violations, file );
 734  
 
 735  28
             sink.table_();
 736  28
             sink.section2_();
 737  28
         }
 738  
 
 739  28
         sink.section1_();
 740  28
     }
 741  
 
 742  
     private void doFileEvents( List<AuditEvent> eventList, String filename )
 743  
     {
 744  28
         for ( AuditEvent event : eventList )
 745  
         {
 746  148
             SeverityLevel level = event.getSeverityLevel();
 747  
 
 748  148
             if ( ( getSeverityLevel() != null ) && !getSeverityLevel().equals( level ) )
 749  
             {
 750  0
                 continue;
 751  
             }
 752  
 
 753  148
             sink.tableRow();
 754  
 
 755  148
             sink.tableCell();
 756  
 
 757  148
             if ( SeverityLevel.INFO.equals( level ) )
 758  
             {
 759  0
                 iconInfo();
 760  
             }
 761  148
             else if ( SeverityLevel.WARNING.equals( level ) )
 762  
             {
 763  8
                 iconWarning();
 764  
             }
 765  140
             else if ( SeverityLevel.ERROR.equals( level ) )
 766  
             {
 767  140
                 iconError();
 768  
             }
 769  
 
 770  148
             sink.tableCell_();
 771  
 
 772  148
             sink.tableCell();
 773  148
             sink.text( event.getMessage() );
 774  148
             sink.tableCell_();
 775  
 
 776  148
             sink.tableCell();
 777  148
             if ( getXrefLocation() != null )
 778  
             {
 779  148
                 sink
 780  
                     .link(
 781  
                         getXrefLocation() + "/" + filename.replaceAll( "\\.java$", ".html" ) + "#" + event.getLine() );
 782  
             }
 783  148
             sink.text( String.valueOf( event.getLine() ) );
 784  148
             if ( getXrefLocation() != null )
 785  
             {
 786  148
                 sink.link_();
 787  
             }
 788  148
             sink.tableCell_();
 789  
 
 790  148
             sink.tableRow_();
 791  148
         }
 792  28
     }
 793  
 
 794  
     public SeverityLevel getSeverityLevel()
 795  
     {
 796  232
         return severityLevel;
 797  
     }
 798  
 
 799  
     public void setSeverityLevel( SeverityLevel severityLevel )
 800  
     {
 801  0
         this.severityLevel = severityLevel;
 802  0
     }
 803  
 
 804  
     public boolean isEnableRulesSummary()
 805  
     {
 806  0
         return enableRulesSummary;
 807  
     }
 808  
 
 809  
     public void setEnableRulesSummary( boolean enableRulesSummary )
 810  
     {
 811  28
         this.enableRulesSummary = enableRulesSummary;
 812  28
     }
 813  
 
 814  
     public boolean isEnableSeveritySummary()
 815  
     {
 816  0
         return enableSeveritySummary;
 817  
     }
 818  
 
 819  
     public void setEnableSeveritySummary( boolean enableSeveritySummary )
 820  
     {
 821  28
         this.enableSeveritySummary = enableSeveritySummary;
 822  28
     }
 823  
 
 824  
     public boolean isEnableFilesSummary()
 825  
     {
 826  0
         return enableFilesSummary;
 827  
     }
 828  
 
 829  
     public void setEnableFilesSummary( boolean enableFilesSummary )
 830  
     {
 831  28
         this.enableFilesSummary = enableFilesSummary;
 832  28
     }
 833  
 
 834  
     public boolean isEnableRSS()
 835  
     {
 836  0
         return enableRSS;
 837  
     }
 838  
 
 839  
     public void setEnableRSS( boolean enableRSS )
 840  
     {
 841  28
         this.enableRSS = enableRSS;
 842  28
     }
 843  
 
 844  
     public String getXrefLocation()
 845  
     {
 846  472
         return xrefLocation;
 847  
     }
 848  
 
 849  
     public void setXrefLocation( String xrefLocation )
 850  
     {
 851  28
         this.xrefLocation = xrefLocation;
 852  28
     }
 853  
 
 854  
     public Configuration getCheckstyleConfig()
 855  
     {
 856  0
         return checkstyleConfig;
 857  
     }
 858  
 
 859  
     public void setCheckstyleConfig( Configuration config )
 860  
     {
 861  28
         this.checkstyleConfig = config;
 862  28
     }
 863  
 
 864  
 }