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( '\\', '/' )
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
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 }