17
17
import org .hjug .cbc .RankedCycle ;
18
18
import org .hjug .cbc .RankedDisharmony ;
19
19
import org .hjug .git .GitLogReader ;
20
+ import org .jgrapht .graph .DefaultEdge ;
20
21
21
22
/**
22
23
* Strictly HTML report that contains no JavaScript
@@ -82,6 +83,9 @@ public class SimpleHtmlReport {
82
83
"Cycle Name" , "Priority" , "Change Proneness Rank" , "Class Count" , "Relationship Count" , "Minimum Cuts"
83
84
};
84
85
86
+ // public final String[] classCycleTableHeadings = {"Classes", "Relationships", "Min Cut Edges"};
87
+ public final String [] classCycleTableHeadings = {"Classes" , "Relationships" };
88
+
85
89
public void execute (
86
90
boolean showDetails , String projectName , String projectVersion , String outputDirectory , File baseDir ) {
87
91
@@ -156,7 +160,8 @@ public void execute(
156
160
}
157
161
List <RankedDisharmony > rankedGodClassDisharmonies = costBenefitCalculator .calculateGodClassCostBenefitValues ();
158
162
List <RankedDisharmony > rankedCBODisharmonies = costBenefitCalculator .calculateCBOCostBenefitValues ();
159
- List <RankedCycle > rankedCycles = costBenefitCalculator .runCycleAnalysis ();
163
+
164
+ List <RankedCycle > rankedCycles = runCycleAnalysis (costBenefitCalculator , outputDirectory );
160
165
161
166
if (rankedGodClassDisharmonies .isEmpty () && rankedCBODisharmonies .isEmpty ()) {
162
167
stringBuilder
@@ -175,7 +180,15 @@ public void execute(
175
180
if (!rankedGodClassDisharmonies .isEmpty () && !rankedCBODisharmonies .isEmpty ()) {
176
181
stringBuilder .append ("<a href=\" #GOD\" >God Classes</a>" );
177
182
stringBuilder .append ("<br/>" );
183
+ }
184
+
185
+ if (!rankedCBODisharmonies .isEmpty ()) {
178
186
stringBuilder .append ("<a href=\" #CBO\" >Highly Coupled Classes</a>" );
187
+ stringBuilder .append ("<br/>" );
188
+ }
189
+
190
+ if (!rankedCycles .isEmpty ()) {
191
+ stringBuilder .append ("<a href=\" #CYCLES\" >Class Cycles</a>" );
179
192
}
180
193
181
194
if (!rankedGodClassDisharmonies .isEmpty ()) {
@@ -197,6 +210,13 @@ public void execute(
197
210
}
198
211
199
212
if (!rankedCycles .isEmpty ()) {
213
+ if (!rankedGodClassDisharmonies .isEmpty () || !rankedCBODisharmonies .isEmpty ()) {
214
+ stringBuilder .append ("<br/>" );
215
+ stringBuilder .append ("<br/>" );
216
+ stringBuilder .append ("<hr/>" );
217
+ stringBuilder .append ("<br/>" );
218
+ stringBuilder .append ("<br/>" );
219
+ }
200
220
renderCycles (outputDirectory , stringBuilder , rankedCycles , formatter );
201
221
}
202
222
@@ -210,13 +230,17 @@ public void execute(
210
230
log .info ("Done! View the report at target/site/{}" , filename );
211
231
}
212
232
233
+ public List <RankedCycle > runCycleAnalysis (CostBenefitCalculator costBenefitCalculator , String outputDirectory ) {
234
+ return costBenefitCalculator .runCycleAnalysis (outputDirectory , false );
235
+ }
236
+
213
237
private void renderCycles (
214
238
String outputDirectory ,
215
239
StringBuilder stringBuilder ,
216
240
List <RankedCycle > rankedCycles ,
217
241
DateTimeFormatter formatter ) {
218
242
219
- stringBuilder .append ("<div style=\" text-align: center;\" ><a id=\" CBO \" ><h1>Class Cycles</h1></a></div>" );
243
+ stringBuilder .append ("<div style=\" text-align: center;\" ><a id=\" CYCLES \" ><h1>Class Cycles</h1></a></div>" );
220
244
221
245
stringBuilder .append (
222
246
"<h2 align=\" center\" >Class Cycles by the numbers: (Refactor starting with Priority 1)</h2>" );
@@ -229,17 +253,23 @@ private void renderCycles(
229
253
}
230
254
231
255
stringBuilder .append ("<tbody>" );
232
- for (RankedCycle rankedCboClassDisharmony : rankedCycles ) {
256
+ for (RankedCycle rankedCycle : rankedCycles ) {
233
257
stringBuilder .append ("<tr>" );
234
258
259
+ StringBuilder edgesToCut = new StringBuilder ();
260
+ for (DefaultEdge minCutEdge : rankedCycle .getMinCutEdges ()) {
261
+ edgesToCut .append (minCutEdge .toString ());
262
+ edgesToCut .append ("</br>" );
263
+ }
264
+
235
265
// "Cycle Name", "Priority", "Change Proneness Rank", "Class Count", "Relationship Count", "Min Cuts"
236
266
String [] rankedCycleData = {
237
- rankedCboClassDisharmony .getCycleName (),
238
- rankedCboClassDisharmony .getPriority ().toString (),
239
- rankedCboClassDisharmony .getChangePronenessRank ().toString (),
240
- String .valueOf (rankedCboClassDisharmony .getCycleNodes ().size ()),
241
- String .valueOf (rankedCboClassDisharmony .getEdgeSet ().size ()),
242
- rankedCboClassDisharmony . getMinCutEdges () .toString ()
267
+ rankedCycle .getCycleName (),
268
+ rankedCycle .getPriority ().toString (),
269
+ rankedCycle .getChangePronenessRank ().toString (),
270
+ String .valueOf (rankedCycle .getCycleNodes ().size ()),
271
+ String .valueOf (rankedCycle .getEdgeSet ().size ()),
272
+ edgesToCut .toString ()
243
273
};
244
274
245
275
for (String rowData : rankedCycleData ) {
@@ -254,6 +284,70 @@ private void renderCycles(
254
284
stringBuilder .append ("</tr></thead>" );
255
285
256
286
stringBuilder .append ("</table>" );
287
+
288
+ for (RankedCycle rankedCycle : rankedCycles ) {
289
+ renderCycleTable (outputDirectory , stringBuilder , rankedCycle , formatter );
290
+ }
291
+ }
292
+
293
+ private void renderCycleTable (
294
+ String outputDirectory , StringBuilder stringBuilder , RankedCycle cycle , DateTimeFormatter formatter ) {
295
+
296
+ stringBuilder .append ("<br/>" );
297
+ stringBuilder .append ("<br/>" );
298
+ stringBuilder .append ("<hr/>" );
299
+ stringBuilder .append ("<br/>" );
300
+ stringBuilder .append ("<br/>" );
301
+
302
+ stringBuilder .append ("<h2 align=\" center\" >Class Cycle : " + cycle .getCycleName () + "</h2>" );
303
+ renderCycleImage (cycle .getCycleName (), stringBuilder , outputDirectory );
304
+
305
+ stringBuilder .append ("<div align=\" center\" >" );
306
+ stringBuilder .append ("<strong>" );
307
+ stringBuilder .append ("\" *\" indicates relationship(s) to remove to decompose cycle" );
308
+ stringBuilder .append ("</strong>" );
309
+ stringBuilder .append ("</div>" );
310
+
311
+ stringBuilder .append ("<table align=\" center\" border=\" 5px\" >" );
312
+
313
+ // Content
314
+ stringBuilder .append ("<thead><tr>" );
315
+ for (String heading : classCycleTableHeadings ) {
316
+ stringBuilder .append ("<th>" ).append (heading ).append ("</th>" );
317
+ }
318
+
319
+ stringBuilder .append ("<tbody>" );
320
+
321
+ for (String vertex : cycle .getVertexSet ()) {
322
+ stringBuilder .append ("<tr>" );
323
+ drawTableCell (vertex , stringBuilder );
324
+ StringBuilder edges = new StringBuilder ();
325
+ for (org .jgrapht .graph .DefaultEdge edge : cycle .getEdgeSet ()) {
326
+ if (edge .toString ().startsWith ("(" + vertex + " :" )) {
327
+ if (cycle .getMinCutEdges ().contains (edge )) {
328
+ edges .append ("<strong>" );
329
+ edges .append (edge + "*" );
330
+ edges .append ("</strong>" );
331
+ } else {
332
+ edges .append (edge );
333
+ }
334
+
335
+ edges .append ("<br/>" );
336
+ }
337
+ }
338
+ drawTableCell (edges .toString (), stringBuilder );
339
+ stringBuilder .append ("</tr>" );
340
+ }
341
+
342
+ stringBuilder .append ("</tbody>" );
343
+
344
+ stringBuilder .append ("</tr></thead>" );
345
+
346
+ stringBuilder .append ("</table>" );
347
+ }
348
+
349
+ public void renderCycleImage (String cycleName , StringBuilder stringBuilder , String outputDirectory ) {
350
+ // empty on purpose
257
351
}
258
352
259
353
private void renderGodClassInfo (
0 commit comments