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