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.List;
24 import java.util.Map;
25 import java.util.ResourceBundle;
26
27 import org.apache.maven.doxia.sink.Sink;
28 import org.apache.maven.plugins.pmd.model.CpdFile;
29 import org.apache.maven.plugins.pmd.model.Duplication;
30 import org.apache.maven.project.MavenProject;
31 import org.codehaus.plexus.util.StringUtils;
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( "https://pmd.github.io/latest/pmd_userdocs_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( CpdFile duplicationMark )
109 {
110
111 String filename = duplicationMark.getPath();
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 = duplicationMark.getLine();
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( xrefLocation + "/" + filename.replaceAll( "\\.java$", ".html" ).replace( '\\', '/' ) + "#L"
135 + 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 public void generate( List<Duplication> duplications )
153 {
154 beginDocument();
155
156 if ( duplications.isEmpty() )
157 {
158 sink.paragraph();
159 sink.text( bundle.getString( "report.cpd.noProblems" ) );
160 sink.paragraph_();
161 }
162
163 for ( Duplication duplication : duplications )
164 {
165 String code = duplication.getCodefragment();
166
167 sink.table();
168 sink.tableRow();
169 sink.tableHeaderCell();
170 sink.text( bundle.getString( "report.cpd.column.file" ) );
171 sink.tableHeaderCell_();
172 if ( aggregate )
173 {
174 sink.tableHeaderCell();
175 sink.text( bundle.getString( "report.cpd.column.project" ) );
176 sink.tableHeaderCell_();
177 }
178 sink.tableHeaderCell();
179 sink.text( bundle.getString( "report.cpd.column.line" ) );
180 sink.tableHeaderCell_();
181 sink.tableRow_();
182
183
184 for ( CpdFile mark : duplication.getFiles() )
185 {
186 generateFileLine( mark );
187 }
188
189
190 sink.tableRow();
191
192 int colspan = 2;
193 if ( aggregate )
194 {
195 ++colspan;
196 }
197
198 sink.rawText( "<td colspan='" + colspan + "'>" );
199 sink.verbatim( null );
200 sink.text( code );
201 sink.verbatim_();
202 sink.rawText( "</td>" );
203 sink.tableRow_();
204 sink.table_();
205 }
206
207 sink.section1_();
208 sink.body_();
209 sink.flush();
210 sink.close();
211 }
212 }