Skip to content

Commit 6f6e742

Browse files
Merge branch 'robcor-develop' into add-csv-report
2 parents 65af55a + 2f3857a commit 6f6e742

File tree

3 files changed

+293
-7
lines changed

3 files changed

+293
-7
lines changed

pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,17 @@
238238
<goal>report</goal>
239239
</goals>
240240
</execution>
241+
242+
<execution>
243+
<id>reportdata</id>
244+
<phase>verify</phase>
245+
<goals>
246+
<goal>report</goal>
247+
</goals>
248+
</execution>
249+
250+
251+
241252
</executions>
242253
</plugin>
243254

refactor-first-maven-plugin/src/main/java/org/hjug/mavenreport/RefactorFirstMavenReport.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ public void execute() {
151151
" <link rel=\"stylesheet\" href=\"./css/maven-theme.css\" />\n" +
152152
" <link rel=\"stylesheet\" href=\"./css/site.css\" />\n" +
153153
" <link rel=\"stylesheet\" href=\"./css/print.css\" media=\"print\" />\n" +
154-
"<script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\"></script><script type=\"text/javascript\" src=\"./gchart.js\"></script> </head>\n" +
154+
"<script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\">" +
155+
"</script><script type=\"text/javascript\" src=\"./gchart.js\"></script> </head>\n" +
155156
" <body class=\"composite\">\n" +
156157
" <div id=\"banner\">\n" +
157158
" <div class=\"clear\">\n" +
@@ -161,8 +162,14 @@ public void execute() {
161162
" <div id=\"breadcrumbs\">\n" +
162163
" <div class=\"xleft\">");
163164

164-
stringBuilder.append("<span id=\"publishDate\">Last Published: ").append(formatter.format(Instant.now())).append("</span>");
165-
stringBuilder.append("<span id=\"projectVersion\"> Version: ").append(projectVersion).append("</span>");
165+
stringBuilder
166+
.append("<span id=\"publishDate\">Last Published: ")
167+
.append(formatter.format(Instant.now()))
168+
.append("</span>");
169+
stringBuilder
170+
.append("<span id=\"projectVersion\"> Version: ")
171+
.append(projectVersion)
172+
.append("</span>");
166173

167174
stringBuilder.append("</div>\n" +
168175
" <div class=\"xright\"> </div>\n" +
@@ -180,8 +187,11 @@ public void execute() {
180187
" <div id=\"bodyColumn\">\n" +
181188
" <div id=\"contentBox\">");
182189

183-
stringBuilder.append("<section>\n" + "<h2>God Class Report for ")
184-
.append(projectName).append(" ").append(projectVersion).append("</h2>\n").append("<div id=\"series_chart_div\"></div>");
190+
stringBuilder
191+
.append("<section>\n" + "<h2>God Class Report for ")
192+
.append(projectName).append(" ").append(projectVersion)
193+
.append("</h2>\n")
194+
.append("<div id=\"series_chart_div\"></div>");
185195

186196
GitLogReader gitLogReader = new GitLogReader();
187197
String projectBaseDir = project.getBasedir().getPath();
@@ -206,7 +216,9 @@ public void execute() {
206216

207217
if(!projectBaseDir.equals(parentOfGitDir)) {
208218
log.warn("Project Base Directory does not match Git Parent Directory");
209-
stringBuilder.append("Project Base Directory does not match Git Parent Directory. Please refer to the report at the root of the site directory.");
219+
stringBuilder.append(
220+
"Project Base Directory does not match Git Parent Directory. " +
221+
"Please refer to the report at the root of the site directory.");
210222
stringBuilder.append(THE_END);
211223
return;
212224
}
@@ -217,7 +229,9 @@ public void execute() {
217229
rankedDisharmonies.sort(Comparator.comparing(RankedDisharmony::getPriority).reversed());
218230

219231
if(rankedDisharmonies.isEmpty()) {
220-
stringBuilder.append("Congratulations! ").append(projectName).append(" ").append(projectVersion).append(" has no God classes!");
232+
stringBuilder.append("Congratulations! ")
233+
.append(projectName).append(" ")
234+
.append(projectVersion).append(" has no God classes!");
221235
log.info("Done! No God classes found!");
222236
stringBuilder.append(THE_END);
223237
writeReportToDisk(filename, stringBuilder);
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
package org.hjug.mavenreport;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.apache.maven.plugin.AbstractMojo;
5+
import org.apache.maven.plugins.annotations.LifecyclePhase;
6+
import org.apache.maven.plugins.annotations.Mojo;
7+
import org.apache.maven.plugins.annotations.Parameter;
8+
import org.apache.maven.plugins.annotations.ResolutionScope;
9+
import org.apache.maven.project.MavenProject;
10+
import org.hjug.cbc.CostBenefitCalculator;
11+
import org.hjug.cbc.RankedDisharmony;
12+
import org.hjug.git.GitLogReader;
13+
14+
import java.io.BufferedWriter;
15+
import java.io.File;
16+
import java.io.FileWriter;
17+
import java.io.IOException;
18+
import java.time.Instant;
19+
import java.time.ZoneId;
20+
import java.time.format.DateTimeFormatter;
21+
import java.time.format.FormatStyle;
22+
import java.util.Comparator;
23+
import java.util.List;
24+
import java.util.Locale;
25+
import java.util.Optional;
26+
27+
@Slf4j
28+
@Mojo(
29+
name = "reportdata",
30+
defaultPhase = LifecyclePhase.SITE,
31+
requiresDependencyResolution = ResolutionScope.RUNTIME,
32+
requiresProject = true,
33+
threadSafe = true,
34+
inheritByDefault = false
35+
)
36+
public class RefactorFirstMavenReportData extends AbstractMojo {
37+
38+
39+
40+
@Parameter(property = "showDetails")
41+
private boolean showDetails = false;
42+
43+
@Parameter(defaultValue = "${project.name}")
44+
private String projectName;
45+
46+
@Parameter(defaultValue = "${project.version}")
47+
private String projectVersion;
48+
49+
@Parameter(readonly = true, defaultValue = "${project}")
50+
private MavenProject project;
51+
52+
@Parameter(property = "project.build.directory")
53+
protected File outputDirectory;
54+
55+
public String getOutputNamePrefix() {
56+
// This report will generate simple-report.html when invoked in a project with `mvn site`
57+
return "RefFirst";
58+
}
59+
60+
public String getName(Locale locale) {
61+
// Name of the report when listed in the project-reports.html page of a project
62+
return "Refactor First Report data";
63+
}
64+
65+
public String getDescription(Locale locale) {
66+
// Description of the report when listed in the project-reports.html page of a project
67+
return "DRACO Ranks the disharmonies in a codebase. The classes that should be refactored first "
68+
+ " have the highest priority values.";
69+
}
70+
71+
@Override
72+
public void execute() {
73+
74+
75+
StringBuilder fileNameSB = new StringBuilder();
76+
String publishedDate = createFileDateTimeFormatter().format(Instant.now());
77+
78+
fileNameSB
79+
.append(getOutputNamePrefix())
80+
.append("_P")
81+
.append(project.getArtifactId())
82+
.append("_PV")
83+
.append(project.getVersion())
84+
.append("_PD")
85+
.append(publishedDate)
86+
.append(".csv");
87+
String filename = fileNameSB.toString();
88+
89+
log.info("Generating {} for {} - {} date: {}", filename, projectName, projectVersion, publishedDate );
90+
91+
StringBuilder contentBuilder = new StringBuilder();
92+
93+
// git management
94+
GitLogReader gitLogReader = new GitLogReader();
95+
String projectBaseDir = project.getBasedir().getPath();
96+
Optional<File> optionalGitDir = Optional.ofNullable(gitLogReader.getGitDir(project.getBasedir()));
97+
File gitDir;
98+
99+
if (optionalGitDir.isPresent()) {
100+
gitDir = optionalGitDir.get();
101+
} else {
102+
log.info("Done! No Git repository found! Please initialize a Git repository and perform an initial commit.");
103+
contentBuilder.append("No Git repository found in project ")
104+
.append(projectName).append(" ")
105+
.append(projectVersion).append(". ");
106+
contentBuilder.append("Please initialize a Git repository and perform an initial commit.");
107+
writeReportToDisk(filename, contentBuilder);
108+
return;
109+
}
110+
111+
String parentOfGitDir = gitDir.getParentFile().getPath();
112+
log.info("Project Base Dir: {} ", projectBaseDir);
113+
log.info("Parent of Git Dir: {}", parentOfGitDir);
114+
115+
if(!projectBaseDir.equals(parentOfGitDir)) {
116+
log.warn("Project Base Directory does not match Git Parent Directory");
117+
contentBuilder.append(
118+
"Project Base Directory does not match Git Parent Directory. " +
119+
"Please refer to the report at the root of the site directory.");
120+
return;
121+
}
122+
123+
// actual calcualte
124+
CostBenefitCalculator costBenefitCalculator = new CostBenefitCalculator();
125+
List<RankedDisharmony> rankedDisharmonies = costBenefitCalculator.calculateCostBenefitValues(projectBaseDir);
126+
127+
rankedDisharmonies.sort(Comparator.comparing(RankedDisharmony::getPriority).reversed());
128+
129+
// perfect score: no god classes
130+
if(rankedDisharmonies.isEmpty()) {
131+
contentBuilder.append("Congratulations! ")
132+
.append(projectName).append(" ")
133+
.append(projectVersion).append(" has no God classes!");
134+
log.info("Done! No God classes found!");
135+
136+
writeReportToDisk(filename, contentBuilder);
137+
return;
138+
}
139+
140+
// create Content
141+
// header
142+
final String[] tableHeadings = getHeaderList();
143+
addsRow(contentBuilder, tableHeadings);
144+
contentBuilder.append("\n");
145+
// rows
146+
for (RankedDisharmony rankedDisharmony : rankedDisharmonies) {
147+
final String[] rankedDisharmonyData = getDataList(rankedDisharmony);
148+
149+
contentBuilder.append(project.getVersion()).append(",");
150+
addsRow(contentBuilder, rankedDisharmonyData);
151+
contentBuilder.append("eol" + "\n");
152+
}
153+
154+
log.info(contentBuilder.toString());
155+
156+
writeReportToDisk(filename, contentBuilder);
157+
}
158+
159+
private DateTimeFormatter createFileDateTimeFormatter() {
160+
return DateTimeFormatter.ofPattern("yyyyMMddhhmm")
161+
.withLocale( Locale.getDefault() )
162+
.withZone( ZoneId.systemDefault() );
163+
}
164+
165+
private DateTimeFormatter createCsvDateTimeFormatter() {
166+
return DateTimeFormatter.ISO_LOCAL_DATE_TIME
167+
.withLocale( Locale.getDefault() )
168+
.withZone( ZoneId.systemDefault() );
169+
}
170+
171+
172+
private String[] getDataList(RankedDisharmony rankedDisharmony ) {
173+
String[] simpleRankedDisharmonyData = { rankedDisharmony.getClassName(),
174+
rankedDisharmony.getPriority().toString(),
175+
rankedDisharmony.getChangePronenessRank().toString(),
176+
rankedDisharmony.getEffortRank().toString(),
177+
rankedDisharmony.getWmc().toString(),
178+
createCsvDateTimeFormatter().format(rankedDisharmony.getMostRecentCommitTime()),
179+
rankedDisharmony.getCommitCount().toString()};
180+
181+
String[] detailedRankedDisharmonyData = { rankedDisharmony.getClassName(),
182+
rankedDisharmony.getPriority().toString(),
183+
rankedDisharmony.getChangePronenessRank().toString(),
184+
rankedDisharmony.getEffortRank().toString(),
185+
rankedDisharmony.getWmc().toString(),
186+
rankedDisharmony.getWmcRank().toString(),
187+
rankedDisharmony.getAtfd().toString(),
188+
rankedDisharmony.getAtfdRank().toString(),
189+
rankedDisharmony.getTcc().toString(),
190+
rankedDisharmony.getTccRank().toString(),
191+
createCsvDateTimeFormatter().format(rankedDisharmony.getFirstCommitTime()),
192+
createCsvDateTimeFormatter().format(rankedDisharmony.getMostRecentCommitTime()),
193+
rankedDisharmony.getCommitCount().toString(),
194+
rankedDisharmony.getPath()};
195+
196+
197+
return showDetails ? detailedRankedDisharmonyData : simpleRankedDisharmonyData;
198+
}
199+
200+
private String[] getHeaderList() {
201+
202+
final String[] simpleTableHeadings = {
203+
"Ver",
204+
"Class",
205+
"Priority",
206+
"Change Proneness Rank",
207+
"Effort Rank",
208+
"Method Count",
209+
"Most Recent Commit Date",
210+
"Commit Count"};
211+
212+
final String[] detailedTableHeadings = {
213+
"Ver",
214+
"Class",
215+
"Priority",
216+
"Change Proneness Rank",
217+
"Effort Rank",
218+
"WMC",
219+
"WMC Rank",
220+
"ATFD",
221+
"ATFD Rank",
222+
"TCC",
223+
"TCC Rank",
224+
"Date of First Commit",
225+
"Most Recent Commit Date",
226+
"Commit Count",
227+
"Full Path"};
228+
229+
return showDetails ? detailedTableHeadings : simpleTableHeadings;
230+
}
231+
232+
private void addsRow(StringBuilder contentBuilder, String[] rankedDisharmonyData) {
233+
for (String rowData : rankedDisharmonyData) {
234+
contentBuilder.append(rowData).append(",");
235+
}
236+
}
237+
238+
private void writeReportToDisk(String filename, StringBuilder stringBuilder) {
239+
String reportOutputDirectory = project.getModel().getReporting().getOutputDirectory();
240+
File reportOutputDir = new File(reportOutputDirectory);
241+
if(!reportOutputDir.exists()) {
242+
reportOutputDir.mkdirs();
243+
}
244+
String pathname = reportOutputDirectory + File.separator + filename;
245+
246+
File reportFile = new File(pathname);
247+
try {
248+
reportFile.createNewFile();
249+
} catch (IOException e) {
250+
log.error("Failure creating chart script file", e);
251+
}
252+
253+
try(BufferedWriter writer = new BufferedWriter(new FileWriter(reportFile))) {
254+
writer.write(stringBuilder.toString());
255+
} catch (IOException e) {
256+
log.error("Error writing chart script file", e);
257+
}
258+
259+
log.info("Done! View the report at target/site/{}", filename);
260+
}
261+
}

0 commit comments

Comments
 (0)