Coverage Report - org.apache.maven.plugin.checkstyle.CheckstyleReportGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
CheckstyleReportGenerator
85%
353/411
60%
64/106
2,618
 
 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: org.apache.maven.plugin.checkstyle.CheckstyleReportGenerator.html 816673 2012-05-08 14:06:16Z hboutemy $
 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  16
     {
 75  16
         this.bundle = bundle;
 76  
 
 77  16
         this.sink = sink;
 78  
 
 79  16
         this.basedir = basedir;
 80  
 
 81  16
         this.siteTool = siteTool;
 82  
 
 83  16
         this.enableRulesSummary = true;
 84  16
         this.enableSeveritySummary = true;
 85  16
         this.enableFilesSummary = true;
 86  16
         this.enableRSS = true;
 87  16
     }
 88  
 
 89  
     public Log getLog()
 90  
     {
 91  28
         if ( this.log == null )
 92  
         {
 93  0
             this.log = new SystemStreamLog();
 94  
         }
 95  28
         return this.log;
 96  
     }
 97  
 
 98  
     public void setLog( Log log )
 99  
     {
 100  16
         this.log = log;
 101  16
     }
 102  
 
 103  
     private String getTitle()
 104  
     {
 105  
         String title;
 106  
 
 107  32
         if ( getSeverityLevel() == null )
 108  
         {
 109  32
             title = bundle.getString( "report.checkstyle.title" );
 110  
         }
 111  
         else
 112  
         {
 113  0
             title = bundle.getString( "report.checkstyle.severity_title" ) + severityLevel.getName();
 114  
         }
 115  
 
 116  32
         return title;
 117  
     }
 118  
 
 119  
     public void generateReport( CheckstyleResults results )
 120  
     {
 121  16
         doHeading();
 122  
 
 123  16
         if ( getSeverityLevel() == null )
 124  
         {
 125  16
             if ( enableSeveritySummary )
 126  
             {
 127  14
                 doSeveritySummary( results );
 128  
             }
 129  
 
 130  16
             if ( enableFilesSummary )
 131  
             {
 132  14
                 doFilesSummary( results );
 133  
             }
 134  
 
 135  16
             if ( enableRulesSummary )
 136  
             {
 137  14
                 doRulesSummary( results );
 138  
             }
 139  
         }
 140  
 
 141  16
         doDetails( results );
 142  16
         sink.body_();
 143  16
         sink.flush();
 144  16
         sink.close();
 145  16
     }
 146  
 
 147  
     private void doHeading()
 148  
     {
 149  16
         sink.head();
 150  16
         sink.title();
 151  16
         sink.text( getTitle() );
 152  16
         sink.title_();
 153  16
         sink.head_();
 154  
 
 155  16
         sink.body();
 156  
 
 157  16
         sink.section1();
 158  16
         sink.sectionTitle1();
 159  16
         sink.text( getTitle() );
 160  16
         sink.sectionTitle1_();
 161  
 
 162  16
         sink.paragraph();
 163  16
         sink.text( bundle.getString( "report.checkstyle.checkstylelink" ) + " " );
 164  16
         sink.link( "http://checkstyle.sourceforge.net/" );
 165  16
         sink.text( "Checkstyle" );
 166  16
         sink.link_();
 167  16
         sink.text( "." );
 168  
 
 169  16
         if ( enableRSS )
 170  
         {
 171  16
             sink.nonBreakingSpace();
 172  16
             sink.link( "checkstyle.rss" );
 173  16
             sink.figure();
 174  16
             sink.figureCaption();
 175  16
             sink.text( "rss feed" );
 176  16
             sink.figureCaption_();
 177  16
             sink.figureGraphics( "images/rss.png" );
 178  16
             sink.figure_();
 179  16
             sink.link_();
 180  
         }
 181  
 
 182  16
         sink.paragraph_();
 183  16
         sink.section1_();
 184  16
     }
 185  
 
 186  
     private void iconSeverity( String level )
 187  
     {
 188  852
         if ( SeverityLevel.INFO.getName().equalsIgnoreCase( level ) )
 189  
         {
 190  2
             iconInfo();
 191  
         }
 192  850
         else if ( SeverityLevel.WARNING.getName().equalsIgnoreCase( level ) )
 193  
         {
 194  4
             iconWarning();
 195  
         }
 196  846
         else if ( SeverityLevel.ERROR.getName().equalsIgnoreCase( level ) )
 197  
         {
 198  846
             iconError();
 199  
         }
 200  852
     }
 201  
 
 202  
     private void iconInfo()
 203  
     {
 204  30
         sink.figure();
 205  30
         sink.figureCaption();
 206  30
         sink.text( bundle.getString( "report.checkstyle.infos" ) );
 207  30
         sink.figureCaption_();
 208  30
         sink.figureGraphics( "images/icon_info_sml.gif" );
 209  30
         sink.figure_();
 210  30
     }
 211  
 
 212  
     private void iconWarning()
 213  
     {
 214  36
         sink.figure();
 215  36
         sink.figureCaption();
 216  36
         sink.text( bundle.getString( "report.checkstyle.warnings" ) );
 217  36
         sink.figureCaption_();
 218  36
         sink.figureGraphics( "images/icon_warning_sml.gif" );
 219  36
         sink.figure_();
 220  36
     }
 221  
 
 222  
     private void iconError()
 223  
     {
 224  954
         sink.figure();
 225  954
         sink.figureCaption();
 226  954
         sink.text( bundle.getString( "report.checkstyle.errors" ) );
 227  954
         sink.figureCaption_();
 228  954
         sink.figureGraphics( "images/icon_error_sml.gif" );
 229  954
         sink.figure_();
 230  954
     }
 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  4254
             ret = config.getAttribute( attributeName );
 252  
         }
 253  4146
         catch ( CheckstyleException e )
 254  
         {
 255  
             // Try to find the attribute in a parent, if there are any
 256  4146
             if ( parentConfigurations != null && !parentConfigurations.isEmpty() )
 257  
             {
 258  1614
                 Configuration parentConfiguration = parentConfigurations.get( parentConfigurations.size() - 1 );
 259  1614
                 List<Configuration> newParentConfigurations = new ArrayList<Configuration>( parentConfigurations );
 260  
                 // Remove the last parent
 261  1614
                 newParentConfigurations.remove( parentConfiguration );
 262  1614
                 ret = getConfigAttribute( parentConfiguration, newParentConfigurations, attributeName, defaultValue );
 263  1614
             }
 264  
             else
 265  
             {
 266  2532
                 ret = defaultValue;
 267  
             }
 268  108
         }
 269  4254
         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  14
         if ( checkstyleConfig == null )
 280  
         {
 281  0
             return;
 282  
         }
 283  
 
 284  14
         sink.section1();
 285  14
         sink.sectionTitle1();
 286  14
         sink.text( bundle.getString( "report.checkstyle.rules" ) );
 287  14
         sink.sectionTitle1_();
 288  
 
 289  14
         sink.table();
 290  
 
 291  14
         sink.tableRow();
 292  14
         sink.tableHeaderCell();
 293  14
         sink.text( bundle.getString( "report.checkstyle.rules" ) );
 294  14
         sink.tableHeaderCell_();
 295  
 
 296  14
         sink.tableHeaderCell();
 297  14
         sink.text( bundle.getString( "report.checkstyle.violations" ) );
 298  14
         sink.tableHeaderCell_();
 299  
 
 300  14
         sink.tableHeaderCell();
 301  14
         sink.text( bundle.getString( "report.checkstyle.column.severity" ) );
 302  14
         sink.tableHeaderCell_();
 303  14
         sink.tableRow_();
 304  
 
 305  
         // Top level should be the checker.
 306  14
         if ( "checker".equalsIgnoreCase( checkstyleConfig.getName() ) )
 307  
         {
 308  14
             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  14
         sink.table_();
 320  
 
 321  14
         sink.section1_();
 322  14
     }
 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  28
         if ( parentConfigurations == null )
 336  
         {
 337  14
             parentConfigurations = new ArrayList<Configuration>();
 338  
         }
 339  
         // The "oldest" parent will be first in the list
 340  28
         parentConfigurations.add( configuration );
 341  
 
 342  28
         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  28
         Configuration configChildren[] = configuration.getChildren();
 362  894
         for ( int cci = 0; cci < configChildren.length; cci++ )
 363  
         {
 364  866
             String ruleName = configChildren[cci].getName();
 365  
 
 366  866
             if ( "TreeWalker".equals( ruleName ) )
 367  
             {
 368  
                 // special sub-case
 369  14
                 doRuleChildren( configChildren[cci], parentConfigurations, results );
 370  
             }
 371  
             else
 372  
             {
 373  852
                 doRuleRow( configChildren[cci], parentConfigurations, ruleName, results );
 374  
             }
 375  
         }
 376  28
     }
 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  852
         sink.tableRow();
 390  852
         sink.tableCell();
 391  852
         sink.text( ruleName );
 392  
 
 393  852
         List<String> attribnames = new ArrayList<String>( Arrays.asList( checkerConfig.getAttributeNames() ) );
 394  852
         attribnames.remove( "severity" ); // special value (deserves unique column)
 395  852
         if ( !attribnames.isEmpty() )
 396  
         {
 397  64
             sink.list();
 398  64
             for ( String name : attribnames )
 399  
             {
 400  84
                 sink.listItem();
 401  
 
 402  84
                 sink.bold();
 403  84
                 sink.text( name );
 404  84
                 sink.bold_();
 405  
 
 406  84
                 String value = getConfigAttribute( checkerConfig, null, name, "" );
 407  
                 // special case, Header.header and RegexpHeader.header
 408  84
                 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  84
                 else if ( "headerFile".equals( name ) && "RegexpHeader".equals( ruleName ) )
 426  
                 {
 427  2
                     sink.text( ": " );
 428  2
                     sink.monospaced();
 429  2
                     sink.text( "\"" );
 430  2
                     if ( basedir != null )
 431  
                     {
 432  
                         // Make the headerFile value relative to ${basedir}
 433  2
                         String path = siteTool.getRelativePath( value, basedir.getAbsolutePath() );
 434  2
                         sink.text( path.replace( '\\', '/' ) );
 435  2
                     }
 436  
                     else
 437  
                     {
 438  0
                         sink.text( value );
 439  
                     }
 440  2
                     sink.text( "\"" );
 441  2
                     sink.monospaced_();
 442  
                 }
 443  
                 else
 444  
                 {
 445  82
                     sink.text( ": " );
 446  82
                     sink.monospaced();
 447  82
                     sink.text( "\"" );
 448  82
                     sink.text( value );
 449  82
                     sink.text( "\"" );
 450  82
                     sink.monospaced_();
 451  
                 }
 452  84
                 sink.listItem_();
 453  84
             }
 454  64
             sink.list_();
 455  
         }
 456  
 
 457  852
         sink.tableCell_();
 458  
 
 459  852
         sink.tableCell();
 460  852
         String fixedmessage = getConfigAttribute( checkerConfig, null, "message", null );
 461  
         // Grab the severity from the rule configuration, use null as default value
 462  852
         String configSeverity = getConfigAttribute( checkerConfig, null, "severity", null );
 463  852
         sink.text( countRuleViolation( results.getFiles().values(), ruleName, fixedmessage,
 464  
                                        configSeverity ) );
 465  852
         sink.tableCell_();
 466  
 
 467  852
         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  852
         configSeverity = getConfigAttribute( checkerConfig, parentConfigurations, "severity", "error" );
 471  852
         iconSeverity( configSeverity );
 472  852
         sink.nonBreakingSpace();
 473  852
         sink.text( StringUtils.capitalise( configSeverity ) );
 474  852
         sink.tableCell_();
 475  
 
 476  852
         sink.tableRow_();
 477  852
     }
 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  852
         long count = 0;
 522  
 
 523  852
         for ( List<AuditEvent> errors : files )
 524  
         {
 525  852
             for ( AuditEvent event : errors )
 526  
             {
 527  4452
                 String eventSrcName = event.getSourceName();
 528  4452
                 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  74
                     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  74
                     else if ( severity != null )
 551  
                     {
 552  4
                         if ( severity.equals( event.getSeverityLevel().getName() ) )
 553  
                         {
 554  4
                             count++;
 555  
                         }
 556  
                     }
 557  
                     else
 558  
                     {
 559  70
                         count++;
 560  
                     }
 561  
                 }
 562  4452
             }
 563  
         }
 564  852
         return String.valueOf( count );
 565  
     }
 566  
 
 567  
     private void doSeveritySummary( CheckstyleResults results )
 568  
     {
 569  14
         sink.section1();
 570  14
         sink.sectionTitle1();
 571  14
         sink.text( bundle.getString( "report.checkstyle.summary" ) );
 572  14
         sink.sectionTitle1_();
 573  
 
 574  14
         sink.table();
 575  
 
 576  14
         sink.tableRow();
 577  14
         sink.tableHeaderCell();
 578  14
         sink.text( bundle.getString( "report.checkstyle.files" ) );
 579  14
         sink.tableHeaderCell_();
 580  
 
 581  14
         sink.tableHeaderCell();
 582  14
         sink.text( bundle.getString( "report.checkstyle.infos" ) );
 583  14
         sink.nonBreakingSpace();
 584  14
         iconInfo();
 585  14
         sink.tableHeaderCell_();
 586  
 
 587  14
         sink.tableHeaderCell();
 588  14
         sink.text( bundle.getString( "report.checkstyle.warnings" ) );
 589  14
         sink.nonBreakingSpace();
 590  14
         iconWarning();
 591  14
         sink.tableHeaderCell_();
 592  
 
 593  14
         sink.tableHeaderCell();
 594  14
         sink.text( bundle.getString( "report.checkstyle.errors" ) );
 595  14
         sink.nonBreakingSpace();
 596  14
         iconError();
 597  14
         sink.tableHeaderCell_();
 598  14
         sink.tableRow_();
 599  
 
 600  14
         sink.tableRow();
 601  14
         sink.tableCell();
 602  14
         sink.text( String.valueOf( results.getFileCount() ) );
 603  14
         sink.tableCell_();
 604  14
         sink.tableCell();
 605  14
         sink.text( String.valueOf( results.getSeverityCount( SeverityLevel.INFO ) ) );
 606  14
         sink.tableCell_();
 607  14
         sink.tableCell();
 608  14
         sink.text( String.valueOf( results.getSeverityCount( SeverityLevel.WARNING ) ) );
 609  14
         sink.tableCell_();
 610  14
         sink.tableCell();
 611  14
         sink.text( String.valueOf( results.getSeverityCount( SeverityLevel.ERROR ) ) );
 612  14
         sink.tableCell_();
 613  14
         sink.tableRow_();
 614  
 
 615  14
         sink.table_();
 616  
 
 617  14
         sink.section1_();
 618  14
     }
 619  
 
 620  
     private void doFilesSummary( CheckstyleResults results )
 621  
     {
 622  14
         sink.section1();
 623  14
         sink.sectionTitle1();
 624  14
         sink.text( bundle.getString( "report.checkstyle.files" ) );
 625  14
         sink.sectionTitle1_();
 626  
 
 627  14
         sink.table();
 628  
 
 629  14
         sink.tableRow();
 630  14
         sink.tableHeaderCell();
 631  14
         sink.text( bundle.getString( "report.checkstyle.files" ) );
 632  14
         sink.tableHeaderCell_();
 633  14
         sink.tableHeaderCell();
 634  14
         sink.text( bundle.getString( "report.checkstyle.infos.abbrev" ) );
 635  14
         sink.nonBreakingSpace();
 636  14
         iconInfo();
 637  14
         sink.tableHeaderCell_();
 638  14
         sink.tableHeaderCell();
 639  14
         sink.text( bundle.getString( "report.checkstyle.warnings.abbrev" ) );
 640  14
         sink.nonBreakingSpace();
 641  14
         iconWarning();
 642  14
         sink.tableHeaderCell_();
 643  14
         sink.tableHeaderCell();
 644  14
         sink.text( bundle.getString( "report.checkstyle.errors.abbrev" ) );
 645  14
         sink.nonBreakingSpace();
 646  14
         iconError();
 647  14
         sink.tableHeaderCell_();
 648  14
         sink.tableRow_();
 649  
 
 650  
         // Sort the files before writing them to the report
 651  14
         List<String> fileList = new ArrayList<String>( results.getFiles().keySet() );
 652  14
         Collections.sort( fileList );
 653  
 
 654  14
         for ( String filename : fileList )
 655  
         {
 656  14
             List<AuditEvent> violations = results.getFileViolations( filename );
 657  14
             if ( violations.isEmpty() )
 658  
             {
 659  
                 // skip files without violations
 660  0
                 continue;
 661  
             }
 662  
 
 663  14
             sink.tableRow();
 664  
 
 665  14
             sink.tableCell();
 666  14
             sink.link( "#" + filename.replace( '/', '.' ) );
 667  14
             sink.text( filename );
 668  14
             sink.link_();
 669  14
             sink.tableCell_();
 670  
 
 671  14
             sink.tableCell();
 672  14
             sink.text( String.valueOf( results.getSeverityCount( violations, SeverityLevel.INFO ) ) );
 673  14
             sink.tableCell_();
 674  
 
 675  14
             sink.tableCell();
 676  14
             sink.text( String.valueOf( results.getSeverityCount( violations, SeverityLevel.WARNING ) ) );
 677  14
             sink.tableCell_();
 678  
 
 679  14
             sink.tableCell();
 680  14
             sink.text( String.valueOf( results.getSeverityCount( violations, SeverityLevel.ERROR ) ) );
 681  14
             sink.tableCell_();
 682  
 
 683  14
             sink.tableRow_();
 684  14
         }
 685  
 
 686  14
         sink.table_();
 687  14
         sink.section1_();
 688  14
     }
 689  
 
 690  
     private void doDetails( CheckstyleResults results )
 691  
     {
 692  
 
 693  16
         sink.section1();
 694  16
         sink.sectionTitle1();
 695  16
         sink.text( bundle.getString( "report.checkstyle.details" ) );
 696  16
         sink.sectionTitle1_();
 697  
 
 698  
         // Sort the files before writing their details to the report
 699  16
         List<String> fileList = new ArrayList<String>( results.getFiles().keySet() );
 700  16
         Collections.sort( fileList );
 701  
 
 702  16
         for ( String file : fileList )
 703  
         {
 704  16
             List<AuditEvent> violations = results.getFileViolations( file );
 705  
 
 706  16
             if ( violations.isEmpty() )
 707  
             {
 708  
                 // skip files without violations
 709  0
                 continue;
 710  
             }
 711  
 
 712  16
             sink.section2();
 713  16
             sink.sectionTitle2();
 714  16
             sink.text( file );
 715  16
             sink.sectionTitle2_();
 716  
 
 717  16
             sink.anchor( file.replace( '/', '.' ) );
 718  16
             sink.anchor_();
 719  
 
 720  16
             sink.table();
 721  16
             sink.tableRow();
 722  16
             sink.tableHeaderCell();
 723  16
             sink.text( bundle.getString( "report.checkstyle.column.violation" ) );
 724  16
             sink.tableHeaderCell_();
 725  16
             sink.tableHeaderCell();
 726  16
             sink.text( bundle.getString( "report.checkstyle.column.message" ) );
 727  16
             sink.tableHeaderCell_();
 728  16
             sink.tableHeaderCell();
 729  16
             sink.text( bundle.getString( "report.checkstyle.column.line" ) );
 730  16
             sink.tableHeaderCell_();
 731  16
             sink.tableRow_();
 732  
 
 733  16
             doFileEvents( violations, file );
 734  
 
 735  16
             sink.table_();
 736  16
             sink.section2_();
 737  16
         }
 738  
 
 739  16
         sink.section1_();
 740  16
     }
 741  
 
 742  
     private void doFileEvents( List<AuditEvent> eventList, String filename )
 743  
     {
 744  16
         for ( AuditEvent event : eventList )
 745  
         {
 746  84
             SeverityLevel level = event.getSeverityLevel();
 747  
 
 748  84
             if ( ( getSeverityLevel() != null ) && !getSeverityLevel().equals( level ) )
 749  
             {
 750  0
                 continue;
 751  
             }
 752  
 
 753  84
             sink.tableRow();
 754  
 
 755  84
             sink.tableCell();
 756  
 
 757  84
             if ( SeverityLevel.INFO.equals( level ) )
 758  
             {
 759  0
                 iconInfo();
 760  
             }
 761  84
             else if ( SeverityLevel.WARNING.equals( level ) )
 762  
             {
 763  4
                 iconWarning();
 764  
             }
 765  80
             else if ( SeverityLevel.ERROR.equals( level ) )
 766  
             {
 767  80
                 iconError();
 768  
             }
 769  
 
 770  84
             sink.tableCell_();
 771  
 
 772  84
             sink.tableCell();
 773  84
             sink.text( event.getMessage() );
 774  84
             sink.tableCell_();
 775  
 
 776  84
             sink.tableCell();
 777  84
             if ( getXrefLocation() != null )
 778  
             {
 779  84
                 sink
 780  
                     .link(
 781  
                         getXrefLocation() + "/" + filename.replaceAll( "\\.java$", ".html" ) + "#" + event.getLine() );
 782  
             }
 783  84
             sink.text( String.valueOf( event.getLine() ) );
 784  84
             if ( getXrefLocation() != null )
 785  
             {
 786  84
                 sink.link_();
 787  
             }
 788  84
             sink.tableCell_();
 789  
 
 790  84
             sink.tableRow_();
 791  84
         }
 792  16
     }
 793  
 
 794  
     public SeverityLevel getSeverityLevel()
 795  
     {
 796  132
         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  16
         this.enableRulesSummary = enableRulesSummary;
 812  16
     }
 813  
 
 814  
     public boolean isEnableSeveritySummary()
 815  
     {
 816  0
         return enableSeveritySummary;
 817  
     }
 818  
 
 819  
     public void setEnableSeveritySummary( boolean enableSeveritySummary )
 820  
     {
 821  16
         this.enableSeveritySummary = enableSeveritySummary;
 822  16
     }
 823  
 
 824  
     public boolean isEnableFilesSummary()
 825  
     {
 826  0
         return enableFilesSummary;
 827  
     }
 828  
 
 829  
     public void setEnableFilesSummary( boolean enableFilesSummary )
 830  
     {
 831  16
         this.enableFilesSummary = enableFilesSummary;
 832  16
     }
 833  
 
 834  
     public boolean isEnableRSS()
 835  
     {
 836  0
         return enableRSS;
 837  
     }
 838  
 
 839  
     public void setEnableRSS( boolean enableRSS )
 840  
     {
 841  16
         this.enableRSS = enableRSS;
 842  16
     }
 843  
 
 844  
     public String getXrefLocation()
 845  
     {
 846  268
         return xrefLocation;
 847  
     }
 848  
 
 849  
     public void setXrefLocation( String xrefLocation )
 850  
     {
 851  16
         this.xrefLocation = xrefLocation;
 852  16
     }
 853  
 
 854  
     public Configuration getCheckstyleConfig()
 855  
     {
 856  0
         return checkstyleConfig;
 857  
     }
 858  
 
 859  
     public void setCheckstyleConfig( Configuration config )
 860  
     {
 861  16
         this.checkstyleConfig = config;
 862  16
     }
 863  
 
 864  
 }