Coverage Report - org.apache.maven.plugin.pmd.CpdReportGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
CpdReportGenerator
87%
85/97
62%
10/16
2,6
 
 1  
 package org.apache.maven.plugin.pmd;
 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.Iterator;
 24  
 import java.util.Map;
 25  
 import java.util.ResourceBundle;
 26  
 
 27  
 import net.sourceforge.pmd.cpd.Match;
 28  
 import net.sourceforge.pmd.cpd.TokenEntry;
 29  
 
 30  
 import org.apache.maven.doxia.sink.Sink;
 31  
 import org.apache.maven.project.MavenProject;
 32  
 import org.codehaus.plexus.util.StringUtils;
 33  
 
 34  
 /**
 35  
  * Class that generated the CPD report.
 36  
  *
 37  
  * @author mperham
 38  
  * @version $Id: CpdReportGenerator.java 1237048 2012-01-28 11:46:21Z rfscholte $
 39  
  */
 40  
 public class CpdReportGenerator
 41  
 {
 42  
     private Sink sink;
 43  
 
 44  
     private Map<File, PmdFileInfo> fileMap;
 45  
 
 46  
     private ResourceBundle bundle;
 47  
 
 48  
     private boolean aggregate;
 49  
 
 50  
     public CpdReportGenerator( Sink sink, Map<File, PmdFileInfo> fileMap, ResourceBundle bundle, boolean aggregate )
 51  16
     {
 52  16
         this.sink = sink;
 53  16
         this.fileMap = fileMap;
 54  16
         this.bundle = bundle;
 55  16
         this.aggregate = aggregate;
 56  16
     }
 57  
 
 58  
     /**
 59  
      * Method that returns the title of the CPD Report
 60  
      *
 61  
      * @return a String that contains the title
 62  
      */
 63  
     private String getTitle()
 64  
     {
 65  32
         return bundle.getString( "report.cpd.title" );
 66  
     }
 67  
 
 68  
     /**
 69  
      * Method that generates the start of the CPD report.
 70  
      */
 71  
     public void beginDocument()
 72  
     {
 73  16
         sink.head();
 74  16
         sink.title();
 75  16
         sink.text( getTitle() );
 76  16
         sink.title_();
 77  16
         sink.head_();
 78  
 
 79  16
         sink.body();
 80  
 
 81  16
         sink.section1();
 82  16
         sink.sectionTitle1();
 83  16
         sink.text( getTitle() );
 84  16
         sink.sectionTitle1_();
 85  
 
 86  16
         sink.paragraph();
 87  16
         sink.text( bundle.getString( "report.cpd.cpdlink" ) + " " );
 88  16
         sink.link( "http://pmd.sourceforge.net/cpd.html" );
 89  16
         sink.text( "CPD" );
 90  16
         sink.link_();
 91  16
         sink.text( " " + AbstractPmdReport.getPmdVersion() + "." );
 92  16
         sink.paragraph_();
 93  
 
 94  16
         sink.section1_();
 95  
 
 96  
         // TODO overall summary
 97  
 
 98  16
         sink.section1();
 99  16
         sink.sectionTitle1();
 100  16
         sink.text( bundle.getString( "report.cpd.dupes" ) );
 101  16
         sink.sectionTitle1_();
 102  
 
 103  
         // TODO files summary
 104  16
     }
 105  
 
 106  
     /**
 107  
      * Method that generates a line of CPD report according to a TokenEntry.
 108  
      */
 109  
     private void generateFileLine( TokenEntry tokenEntry )
 110  
     {
 111  
         // Get information for report generation
 112  32
         String filename = tokenEntry.getTokenSrcID();
 113  32
         File file = new File( filename );
 114  32
         PmdFileInfo fileInfo = fileMap.get( file );
 115  32
         File sourceDirectory = fileInfo.getSourceDirectory();
 116  32
         filename = StringUtils.substring( filename, sourceDirectory.getAbsolutePath().length() + 1 );
 117  32
         String xrefLocation = fileInfo.getXrefLocation();
 118  32
         MavenProject projectFile = fileInfo.getProject();
 119  32
         int line = tokenEntry.getBeginLine();
 120  
 
 121  32
         sink.tableRow();
 122  32
         sink.tableCell();
 123  32
         sink.text( filename );
 124  32
         sink.tableCell_();
 125  32
         if ( aggregate )
 126  
         {
 127  0
             sink.tableCell();
 128  0
             sink.text( projectFile.getName() );
 129  0
             sink.tableCell_();
 130  
         }
 131  32
         sink.tableCell();
 132  
 
 133  32
         if ( xrefLocation != null )
 134  
         {
 135  0
             sink.link( xrefLocation + "/" + filename.replaceAll( "\\.java$", ".html" ).replace( '\\', '/' )
 136  
                     + "#" + line );
 137  
         }
 138  32
         sink.text( String.valueOf( line ) );
 139  32
         if ( xrefLocation != null )
 140  
         {
 141  0
             sink.link_();
 142  
         }
 143  
 
 144  32
         sink.tableCell_();
 145  32
         sink.tableRow_();
 146  32
     }
 147  
 
 148  
     /**
 149  
      * Method that generates the contents of the CPD report
 150  
      *
 151  
      * @param matches
 152  
      */
 153  
     @SuppressWarnings( "deprecation" )
 154  
     public void generate( Iterator<Match> matches )
 155  
     {
 156  16
         beginDocument();
 157  
 
 158  16
         if ( !matches.hasNext() )
 159  
         {
 160  0
             sink.paragraph();
 161  0
             sink.text( bundle.getString( "report.cpd.noProblems" ) );
 162  0
             sink.paragraph_();
 163  
         }
 164  
 
 165  32
         while ( matches.hasNext() )
 166  
         {
 167  16
             Match match = matches.next();
 168  
             
 169  16
             String code = match.getSourceCodeSlice();
 170  
             
 171  16
             sink.table();
 172  16
             sink.tableRow();
 173  16
             sink.tableHeaderCell();
 174  16
             sink.text( bundle.getString( "report.cpd.column.file" ) );
 175  16
             sink.tableHeaderCell_();
 176  16
             if ( aggregate )
 177  
             {
 178  0
                 sink.tableHeaderCell();
 179  0
                 sink.text( bundle.getString( "report.cpd.column.project" ) );
 180  0
                 sink.tableHeaderCell_();
 181  
             }
 182  16
             sink.tableHeaderCell();
 183  16
             sink.text( bundle.getString( "report.cpd.column.line" ) );
 184  16
             sink.tableHeaderCell_();
 185  16
             sink.tableRow_();
 186  
 
 187  
             // Iterating on every token entry
 188  16
             for ( Iterator<TokenEntry> occurrences = match.iterator(); occurrences.hasNext(); )
 189  
             {
 190  
 
 191  32
                 TokenEntry mark = occurrences.next();
 192  32
                 generateFileLine( mark );
 193  32
             }
 194  
            
 195  
             // Source snippet
 196  16
             sink.tableRow();
 197  
 
 198  
 
 199  16
             int colspan = 2;
 200  16
             if ( aggregate )
 201  
             {
 202  0
                 ++colspan;
 203  
             }
 204  
             // TODO Cleaner way to do this?
 205  16
             sink.rawText( "<td colspan='" + colspan + "'>" );
 206  16
             sink.verbatim( false );
 207  16
             sink.text( code );
 208  16
             sink.verbatim_();
 209  16
             sink.rawText( "</td>" );
 210  16
             sink.tableRow_();
 211  16
             sink.table_();
 212  16
         }
 213  
 
 214  16
         sink.section1_();
 215  16
         sink.body_();
 216  16
         sink.flush();
 217  16
         sink.close();
 218  16
     }
 219  
 }