View Javadoc

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