1   package org.apache.maven.plugin.pmd;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
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  
36  
37  
38  
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      {
52          this.sink = sink;
53          this.fileMap = fileMap;
54          this.bundle = bundle;
55          this.aggregate = aggregate;
56      }
57  
58      
59  
60  
61  
62  
63      private String getTitle()
64      {
65          return bundle.getString( "report.cpd.title" );
66      }
67  
68      
69  
70  
71      public void beginDocument()
72      {
73          sink.head();
74          sink.title();
75          sink.text( getTitle() );
76          sink.title_();
77          sink.head_();
78  
79          sink.body();
80  
81          sink.section1();
82          sink.sectionTitle1();
83          sink.text( getTitle() );
84          sink.sectionTitle1_();
85  
86          sink.paragraph();
87          sink.text( bundle.getString( "report.cpd.cpdlink" ) + " " );
88          sink.link( "http://pmd.sourceforge.net/cpd.html" );
89          sink.text( "CPD" );
90          sink.link_();
91          sink.text( " " + AbstractPmdReport.getPmdVersion() + "." );
92          sink.paragraph_();
93  
94          sink.section1_();
95  
96          
97  
98          sink.section1();
99          sink.sectionTitle1();
100         sink.text( bundle.getString( "report.cpd.dupes" ) );
101         sink.sectionTitle1_();
102 
103         
104     }
105 
106     
107 
108 
109     private void generateFileLine( TokenEntry tokenEntry )
110     {
111         
112         String filename = tokenEntry.getTokenSrcID();
113         File file = new File( filename );
114         PmdFileInfo fileInfo = fileMap.get( file );
115         File sourceDirectory = fileInfo.getSourceDirectory();
116         filename = StringUtils.substring( filename, sourceDirectory.getAbsolutePath().length() + 1 );
117         String xrefLocation = fileInfo.getXrefLocation();
118         MavenProject projectFile = fileInfo.getProject();
119         int line = tokenEntry.getBeginLine();
120 
121         sink.tableRow();
122         sink.tableCell();
123         sink.text( filename );
124         sink.tableCell_();
125         if ( aggregate )
126         {
127             sink.tableCell();
128             sink.text( projectFile.getName() );
129             sink.tableCell_();
130         }
131         sink.tableCell();
132 
133         if ( xrefLocation != null )
134         {
135             sink.link( xrefLocation + "/" + filename.replaceAll( "\\.java$", ".html" ).replace( '\\', '/' ) + "#L"
136                 + line );
137         }
138         sink.text( String.valueOf( line ) );
139         if ( xrefLocation != null )
140         {
141             sink.link_();
142         }
143 
144         sink.tableCell_();
145         sink.tableRow_();
146     }
147 
148     
149 
150 
151 
152 
153     @SuppressWarnings( "deprecation" )
154     public void generate( Iterator<Match> matches )
155     {
156         beginDocument();
157 
158         if ( !matches.hasNext() )
159         {
160             sink.paragraph();
161             sink.text( bundle.getString( "report.cpd.noProblems" ) );
162             sink.paragraph_();
163         }
164 
165         while ( matches.hasNext() )
166         {
167             Match match = matches.next();
168 
169             String code = match.getSourceCodeSlice();
170 
171             sink.table();
172             sink.tableRow();
173             sink.tableHeaderCell();
174             sink.text( bundle.getString( "report.cpd.column.file" ) );
175             sink.tableHeaderCell_();
176             if ( aggregate )
177             {
178                 sink.tableHeaderCell();
179                 sink.text( bundle.getString( "report.cpd.column.project" ) );
180                 sink.tableHeaderCell_();
181             }
182             sink.tableHeaderCell();
183             sink.text( bundle.getString( "report.cpd.column.line" ) );
184             sink.tableHeaderCell_();
185             sink.tableRow_();
186 
187             
188             for ( Iterator<TokenEntry> occurrences = match.iterator(); occurrences.hasNext(); )
189             {
190 
191                 TokenEntry mark = occurrences.next();
192                 generateFileLine( mark );
193             }
194 
195             
196             sink.tableRow();
197 
198             int colspan = 2;
199             if ( aggregate )
200             {
201                 ++colspan;
202             }
203             
204             sink.rawText( "<td colspan='" + colspan + "'>" );
205             sink.verbatim( false );
206             sink.text( code );
207             sink.verbatim_();
208             sink.rawText( "</td>" );
209             sink.tableRow_();
210             sink.table_();
211         }
212 
213         sink.section1_();
214         sink.body_();
215         sink.flush();
216         sink.close();
217     }
218 }