JSONMetricsReport.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.*;
- import static java.util.stream.Collectors.*;
- public class JSONMetricsReport extends MetricsReport {
- public JSONMetricsReport(PrintWriter out) {
- super(out);
- }
- public void process(MetricsGatherer metrics) {
- print("{");
- printProgrammingElementStats(metrics);
- print(",");
- printDependencyStats(metrics);
- if (isShowingClassesPerPackageHistogram() ||
- isShowingFeaturesPerClassHistogram() ||
- isShowingInboundsPerPackageHistogram() ||
- isShowingOutboundsPerPackageHistogram() ||
- isShowingInboundsPerClassHistogram() ||
- isShowingOutboundsPerClassHistogram() ||
- isShowingInboundsPerFeatureHistogram() ||
- isShowingOutboundsPerFeatureHistogram()) {
- print(",");
- printHistograms(metrics);
- }
- if (isShowingClassesPerPackageChart() ||
- isShowingFeaturesPerClassChart() ||
- isShowingInboundsPerPackageChart() ||
- isShowingOutboundsPerPackageChart() ||
- isShowingInboundsPerClassChart() ||
- isShowingOutboundsPerClassChart() ||
- isShowingInboundsPerFeatureChart() ||
- isShowingOutboundsPerFeatureChart()) {
- print(",");
- printChart(metrics);
- }
- print("}");
- println();
- }
- private void printProgrammingElementStats(MetricsGatherer metrics) {
- printProgrammingElementStats("packages", metrics.getPackages());
- print(",");
- printProgrammingElementStats("classes", metrics.getClasses());
- print(",");
- printProgrammingElementStats("features", metrics.getFeatures());
- }
- private void printProgrammingElementStats(String label, Collection<? extends Node> nodes) {
- var nbElements = nodes.size();
- var nbConfirmedElements = countConfirmedNodes(nodes);
- var ratio = nbConfirmedElements / (double) nbElements;
- print("\"" + label + "\":{");
- print("\"count\":" + nbElements);
- print(",");
- print("\"confirmed\":" + nbConfirmedElements);
- print(",");
- print("\"ratio\":" + formatValue(ratio));
- if (isListingElements()) {
- print(",");
- print("\"elements\": [");
- print(renderNodes(nodes));
- print("]");
- }
- print("}");
- }
- private String renderNodes(Collection<? extends Node> nodes) {
- return nodes.stream()
- .sorted()
- .map(node -> "{\"name\":\"" + node.getName() + "\",\"simpleName\":\"" + node.getSimpleName() + "\",\"confirmed\":" + node.isConfirmed() + "}")
- .collect(joining(","));
- }
- private void printDependencyStats(MetricsGatherer metrics) {
- print("\"outbounds\": {");
- print("\"packages\":" + metrics.getNbOutboundPackages() + ",");
- print("\"packageRatio\":" + formatValue(metrics.getNbOutboundPackages() / (double) metrics.getPackages().size()) + ",");
- print("\"classes\":" + metrics.getNbOutboundClasses() + ",");
- print("\"classRatio\":" + formatValue(metrics.getNbOutboundClasses() / (double) metrics.getClasses().size()) + ",");
- print("\"features\":" + metrics.getNbOutboundFeatures() + ",");
- print("\"featureRatio\":" + formatValue(metrics.getNbOutboundFeatures() / (double) metrics.getFeatures().size()) + ",");
- print("\"total\":" + metrics.getNbOutbound());
- print("}");
- print(",");
- print("\"inbounds\": {");
- print("\"packages\":" + metrics.getNbInboundPackages() + ",");
- print("\"packageRatio\":" + formatValue(metrics.getNbInboundPackages() / (double) metrics.getPackages().size()) + ",");
- print("\"classes\":" + metrics.getNbInboundClasses() + ",");
- print("\"classRatio\":" + formatValue(metrics.getNbInboundClasses() / (double) metrics.getClasses().size()) + ",");
- print("\"features\":" + metrics.getNbInboundFeatures() + ",");
- print("\"featureRatio\":" + formatValue(metrics.getNbInboundFeatures() / (double) metrics.getFeatures().size()) + ",");
- print("\"total\":" + metrics.getNbInbound());
- print("}");
- }
- private void printHistograms(MetricsGatherer metrics) {
- var histograms = new HashMap<String, Map<Long, Long>>();
- if (isShowingClassesPerPackageHistogram()) {
- histograms.put("classesPerPackage", metrics.getHistogram(MetricsGatherer.CLASSES_PER_PACKAGE));
- }
- if (isShowingFeaturesPerClassHistogram()) {
- histograms.put("featuresPerClass", metrics.getHistogram(MetricsGatherer.FEATURES_PER_CLASS));
- }
- if (isShowingInboundsPerPackageHistogram()) {
- histograms.put("inboundsPerPackage", metrics.getHistogram(MetricsGatherer.INBOUNDS_PER_PACKAGE));
- }
- if (isShowingOutboundsPerPackageHistogram()) {
- histograms.put("outboundsPerPackage", metrics.getHistogram(MetricsGatherer.OUTBOUNDS_PER_PACKAGE));
- }
- if (isShowingInboundsPerClassHistogram()) {
- histograms.put("inboundsPerClass", metrics.getHistogram(MetricsGatherer.OUTBOUNDS_PER_CLASS));
- }
- if (isShowingOutboundsPerClassHistogram()) {
- histograms.put("outboundsPerClass", metrics.getHistogram(MetricsGatherer.OUTBOUNDS_PER_CLASS));
- }
- if (isShowingInboundsPerFeatureHistogram()) {
- histograms.put("inboundsPerFeature", metrics.getHistogram(MetricsGatherer.OUTBOUNDS_PER_FEATURE));
- }
- if (isShowingOutboundsPerFeatureHistogram()) {
- histograms.put("outboundsPerFeature", metrics.getHistogram(MetricsGatherer.OUTBOUNDS_PER_FEATURE));
- }
- print("\"histograms\":{");
- print(
- histograms.entrySet().stream()
- .map(entry ->
- "\"" + entry.getKey() + "\":[" + new TreeMap<>(entry.getValue()).entrySet().stream().map(pair -> "[" + pair.getKey() + "," + pair.getValue() + "]").collect(joining(",")) + "]")
- .collect(joining(","))
- );
- print("}");
- }
- private void printChart(MetricsGatherer metrics) {
- print("\"chart\":[");
- // Headings
- print("[");
- 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\"");
- }
- print("]");
- // Data
- for (int k=0; k<=metrics.getChartMaximum(); k++) {
- long[] dataPoint = metrics.getChartData(k);
- print(",[");
- 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]);
- }
- print("]");
- }
- print("]");
- }
- private String formatValue(double value) {
- if (Double.isNaN(value) || Double.isInfinite(value)) {
- return "null";
- }
- return String.valueOf(value);
- }
- }