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