1 package org.apache.maven.plugins.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 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<Mark> occurrences = match.iterator(); occurrences.hasNext(); )
189 {
190
191 TokenEntry mark = occurrences.next().getToken();
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( null );
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 }