TextMetricsReport.java
/*
* Copyright (c) 2001-2024, Jean Tessier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Jean Tessier nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jeantessier.dependency;
import java.io.*;
import java.util.*;
public class TextMetricsReport extends MetricsReport {
public TextMetricsReport(PrintWriter out) {
super(out);
}
public void process(MetricsGatherer metrics) {
printProgrammingElements(metrics);
println();
printDependencyStats(metrics);
printHistograms(metrics);
printChart(metrics);
}
private void printProgrammingElements(MetricsGatherer metrics) {
int nbPackages = metrics.getPackages().size();
print(nbPackages + " package(s)");
if (nbPackages > 0) {
var nbConfirmedPackages = countConfirmedNodes(metrics.getPackages());
print(" (" + nbConfirmedPackages + " confirmed, " + (nbConfirmedPackages / (double) nbPackages) + ")");
}
println();
if (isListingElements()) {
metrics.getPackages().stream().sorted().forEach(node -> println(" " + node));
}
int nbClasses = metrics.getClasses().size();
print(nbClasses + " class(es)");
if (nbClasses > 0) {
var nbConfirmedClasses = countConfirmedNodes(metrics.getClasses());
print(" (" + nbConfirmedClasses + " confirmed, " + (nbConfirmedClasses / (double) nbClasses) + ")");
}
println();
if (isListingElements()) {
metrics.getClasses().stream().sorted().forEach(node -> println(" " + node));
}
int nbFeatures = metrics.getFeatures().size();
print(nbFeatures + " feature(s)");
if (nbFeatures > 0) {
var nbConfirmedFeatures = countConfirmedNodes(metrics.getFeatures());
print(" (" + nbConfirmedFeatures + " confirmed, " + (nbConfirmedFeatures / (double) nbFeatures) + ")");
}
println();
if (isListingElements()) {
metrics.getFeatures().stream().sorted().forEach(node -> println(" " + node));
}
}
private void printDependencyStats(MetricsGatherer metrics) {
println(metrics.getNbOutbound() + " outbound link(s)");
int nbPackages = metrics.getPackages().size();
long nbOutboundPackages = metrics.getNbOutboundPackages();
print(" " + nbOutboundPackages + " from package(s)");
if (nbOutboundPackages > 0 && nbPackages > 0) {
print(" (on average " + (nbOutboundPackages / (double) nbPackages) + " per package)");
}
println();
int nbClasses = metrics.getClasses().size();
long nbOutboundClasses = metrics.getNbOutboundClasses();
print(" " + nbOutboundClasses + " from class(es)");
if (nbOutboundClasses > 0 && nbClasses > 0) {
print(" (on average " + (nbOutboundClasses / (double) nbClasses) + " per class)");
}
println();
int nbFeatures = metrics.getFeatures().size();
long nbOutboundFeatures = metrics.getNbOutboundFeatures();
print(" " + nbOutboundFeatures + " from feature(s)");
if (nbOutboundFeatures > 0 && nbFeatures > 0) {
print(" (on average " + (nbOutboundFeatures / (double) nbFeatures) + " per feature)");
}
println();
println(metrics.getNbInbound() + " inbound link(s)");
long nbInboundPackages = metrics.getNbInboundPackages();
print(" " + nbInboundPackages + " to package(s)");
if (nbInboundPackages > 0 && nbPackages > 0) {
print(" (on average " + (nbInboundPackages / (double) nbPackages) + " per package)");
}
println();
long nbInboundClasses = metrics.getNbInboundClasses();
print(" " + nbInboundClasses + " to class(es)");
if (nbInboundClasses > 0 && nbClasses > 0) {
print(" (on average " + (nbInboundClasses / (double) nbClasses) + " per class)");
}
println();
long nbInboundFeatures = metrics.getNbInboundFeatures();
print(" " + nbInboundFeatures + " to feature(s)");
if (nbInboundFeatures > 0 && nbFeatures > 0) {
print(" (on average " + (nbInboundFeatures / (double) nbFeatures) + " per feature)");
}
println();
}
private void printHistograms(MetricsGatherer metrics) {
if (isShowingClassesPerPackageHistogram()) {
printHistogram(metrics, MetricsGatherer.CLASSES_PER_PACKAGE, "Classes per package histogram");
}
if (isShowingFeaturesPerClassHistogram()) {
printHistogram(metrics, MetricsGatherer.FEATURES_PER_CLASS, "Features per class histogram");
}
if (isShowingInboundsPerPackageHistogram()) {
printHistogram(metrics, MetricsGatherer.INBOUNDS_PER_PACKAGE, "Inbounds per package histogram");
}
if (isShowingOutboundsPerPackageHistogram()) {
printHistogram(metrics, MetricsGatherer.OUTBOUNDS_PER_PACKAGE, "Outbounds per package histogram");
}
if (isShowingInboundsPerClassHistogram()) {
printHistogram(metrics, MetricsGatherer.OUTBOUNDS_PER_CLASS, "Inbounds per class histogram");
}
if (isShowingOutboundsPerClassHistogram()) {
printHistogram(metrics, MetricsGatherer.OUTBOUNDS_PER_CLASS, "Outbounds per class histogram");
}
if (isShowingInboundsPerFeatureHistogram()) {
printHistogram(metrics, MetricsGatherer.OUTBOUNDS_PER_FEATURE, "Inbounds per feature histogram");
}
if (isShowingOutboundsPerFeatureHistogram()) {
printHistogram(metrics, MetricsGatherer.OUTBOUNDS_PER_FEATURE, "Outbounds per feature histogram");
}
}
private void printHistogram(MetricsGatherer metrics, int chart, String title) {
println();
println(title);
new TreeMap<>(metrics.getHistogram(chart)).forEach((n, cardinality) -> println(n + ": " + cardinality));
}
private void printChart(MetricsGatherer metrics) {
if (isShowingClassesPerPackageChart() ||
isShowingFeaturesPerClassChart() ||
isShowingInboundsPerPackageChart() ||
isShowingOutboundsPerPackageChart() ||
isShowingInboundsPerClassChart() ||
isShowingOutboundsPerClassChart() ||
isShowingInboundsPerFeatureChart() ||
isShowingOutboundsPerFeatureChart()) {
println();
print("n");
if (isShowingClassesPerPackageChart()) {
print(", \"classes per package\"");
}
if (isShowingFeaturesPerClassChart()) {
print(", \"features per class\"");
}
if (isShowingInboundsPerPackageChart()) {
print(", \"inbounds per package\"");
}
if (isShowingOutboundsPerPackageChart()) {
print(", \"outbounds per package\"");
}
if (isShowingInboundsPerClassChart()) {
print(", \"inbounds per class\"");
}
if (isShowingOutboundsPerClassChart()) {
print(", \"outbounds per class\"");
}
if (isShowingInboundsPerFeatureChart()) {
print(", \"inbounds per feature\"");
}
if (isShowingOutboundsPerFeatureChart()) {
print(", \"outbounds per feature\"");
}
println();
for (int k=0; k<=metrics.getChartMaximum(); k++) {
long[] dataPoint = metrics.getChartData(k);
print(k);
if (isShowingClassesPerPackageChart()) {
print(", " + dataPoint[MetricsGatherer.CLASSES_PER_PACKAGE]);
}
if (isShowingFeaturesPerClassChart()) {
print(", " + dataPoint[MetricsGatherer.FEATURES_PER_CLASS]);
}
if (isShowingInboundsPerPackageChart()) {
print(", " + dataPoint[MetricsGatherer.INBOUNDS_PER_PACKAGE]);
}
if (isShowingOutboundsPerPackageChart()) {
print(", " + dataPoint[MetricsGatherer.OUTBOUNDS_PER_PACKAGE]);
}
if (isShowingInboundsPerClassChart()) {
print(", " + dataPoint[MetricsGatherer.INBOUNDS_PER_CLASS]);
}
if (isShowingOutboundsPerClassChart()) {
print(", " + dataPoint[MetricsGatherer.OUTBOUNDS_PER_CLASS]);
}
if (isShowingInboundsPerFeatureChart()) {
print(", " + dataPoint[MetricsGatherer.INBOUNDS_PER_FEATURE]);
}
if (isShowingOutboundsPerFeatureChart()) {
print(", " + dataPoint[MetricsGatherer.OUTBOUNDS_PER_FEATURE]);
}
println();
}
}
}
}