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