DependencyMetrics.java

  1. /*
  2.  *  Copyright (c) 2001-2024, Jean Tessier
  3.  *  All rights reserved.
  4.  *  
  5.  *  Redistribution and use in source and binary forms, with or without
  6.  *  modification, are permitted provided that the following conditions
  7.  *  are met:
  8.  *  
  9.  *      * Redistributions of source code must retain the above copyright
  10.  *        notice, this list of conditions and the following disclaimer.
  11.  *  
  12.  *      * Redistributions in binary form must reproduce the above copyright
  13.  *        notice, this list of conditions and the following disclaimer in the
  14.  *        documentation and/or other materials provided with the distribution.
  15.  *  
  16.  *      * Neither the name of Jean Tessier nor the names of his contributors
  17.  *        may be used to endorse or promote products derived from this software
  18.  *        without specific prior written permission.
  19.  *  
  20.  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21.  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22.  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23.  *  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
  24.  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25.  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26.  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27.  *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28.  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29.  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30.  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31.  */

  32. package com.jeantessier.dependencyfinder.ant;

  33. import java.io.*;

  34. import javax.xml.parsers.*;

  35. import org.apache.tools.ant.*;

  36. import org.xml.sax.*;

  37. import com.jeantessier.dependency.*;

  38. public class DependencyMetrics extends GraphTask {
  39.     private String  scopeIncludes = "//";
  40.     private String  scopeExcludes = "";
  41.     private boolean packageScope;
  42.     private String  packageScopeIncludes = "";
  43.     private String  packageScopeExcludes = "";
  44.     private boolean classScope;
  45.     private String  classScopeIncludes = "";
  46.     private String  classScopeExcludes = "";
  47.     private boolean featureScope;
  48.     private String  featureScopeIncludes = "";
  49.     private String  featureScopeExcludes = "";
  50.     private String  filterIncludes = "//";
  51.     private String  filterExcludes = "";
  52.     private boolean packageFilter;
  53.     private String  packageFilterIncludes = "";
  54.     private String  packageFilterExcludes = "";
  55.     private boolean classFilter;
  56.     private String  classFilterIncludes = "";
  57.     private String  classFilterExcludes = "";
  58.     private boolean featureFilter;
  59.     private String  featureFilterIncludes = "";
  60.     private String  featureFilterExcludes = "";

  61.     private boolean list = false;

  62.     private boolean chartClassesPerPackage   = false;
  63.     private boolean chartFeaturesPerClass    = false;
  64.     private boolean chartInboundsPerPackage  = false;
  65.     private boolean chartOutboundsPerPackage = false;
  66.     private boolean chartInboundsPerClass    = false;
  67.     private boolean chartOutboundsPerClass   = false;
  68.     private boolean chartInboundsPerFeature  = false;
  69.     private boolean chartOutboundsPerFeature = false;

  70.     private boolean histogramClassesPerPackage   = false;
  71.     private boolean histogramFeaturesPerClass    = false;
  72.     private boolean histogramInboundsPerPackage  = false;
  73.     private boolean histogramOutboundsPerPackage = false;
  74.     private boolean histogramInboundsPerClass    = false;
  75.     private boolean histogramOutboundsPerClass   = false;
  76.     private boolean histogramInboundsPerFeature  = false;
  77.     private boolean histogramOutboundsPerFeature = false;

  78.     private boolean json = false;

  79.     public String getScopeincludes() {
  80.         return scopeIncludes;
  81.     }

  82.     public void setScopeincludes(String scopeIncludes) {
  83.         this.scopeIncludes = scopeIncludes;
  84.     }
  85.    
  86.     public String getScopeexcludes() {
  87.         return scopeExcludes;
  88.     }

  89.     public void setScopeexcludes(String scopeExcludes) {
  90.         this.scopeExcludes = scopeExcludes;
  91.     }

  92.     public boolean getPackagescope() {
  93.         return packageScope;
  94.     }

  95.     public void setPackagescope(boolean packageScope) {
  96.         this.packageScope = packageScope;
  97.     }
  98.    
  99.     public String getPackagescopeincludes() {
  100.         return packageScopeIncludes;
  101.     }

  102.     public void setPackagescopeincludes(String packageScopeIncludes) {
  103.         this.packageScopeIncludes = packageScopeIncludes;
  104.     }
  105.    
  106.     public String getPackagescopeexcludes() {
  107.         return packageScopeExcludes;
  108.     }

  109.     public void setPackagescopeexcludes(String packageScopeExcludes) {
  110.         this.packageScopeExcludes = packageScopeExcludes;
  111.     }

  112.     public boolean getClassscope() {
  113.         return classScope;
  114.     }

  115.     public void setClassscope(boolean classScope) {
  116.         this.classScope = classScope;
  117.     }
  118.    
  119.     public String getClassscopeincludes() {
  120.         return classScopeIncludes;
  121.     }

  122.     public void setClassscopeincludes(String classScopeIncludes) {
  123.         this.classScopeIncludes = classScopeIncludes;
  124.     }
  125.    
  126.     public String getClassscopeexcludes() {
  127.         return classScopeExcludes;
  128.     }

  129.     public void setClassscopeexcludes(String classScopeExcludes) {
  130.         this.classScopeExcludes = classScopeExcludes;
  131.     }

  132.     public boolean getFeaturescope() {
  133.         return featureScope;
  134.     }

  135.     public void setFeaturescope(boolean featureScope) {
  136.         this.featureScope = featureScope;
  137.     }
  138.    
  139.     public String getFeaturescopeincludes() {
  140.         return featureScopeIncludes;
  141.     }

  142.     public void setFeaturescopeincludes(String featureScopeIncludes) {
  143.         this.featureScopeIncludes = featureScopeIncludes;
  144.     }
  145.    
  146.     public String getFeaturescopeexcludes() {
  147.         return featureScopeExcludes;
  148.     }

  149.     public void setFeaturescopeexcludes(String featureScopeExcludes) {
  150.         this.featureScopeExcludes = featureScopeExcludes;
  151.     }

  152.     public String getFilterincludes() {
  153.         return filterIncludes;
  154.     }

  155.     public void setFilterincludes(String filterIncludes) {
  156.         this.filterIncludes = filterIncludes;
  157.     }
  158.    
  159.     public String getFilterexcludes() {
  160.         return filterExcludes;
  161.     }

  162.     public void setFilterexcludes(String filterExcludes) {
  163.         this.filterExcludes = filterExcludes;
  164.     }

  165.     public boolean getPackagefilter() {
  166.         return packageFilter;
  167.     }

  168.     public void setPackagefilter(boolean packageFilter) {
  169.         this.packageFilter = packageFilter;
  170.     }
  171.    
  172.     public String getPackagefilterincludes() {
  173.         return packageFilterIncludes;
  174.     }

  175.     public void setPackagefilterincludes(String packageFilterIncludes) {
  176.         this.packageFilterIncludes = packageFilterIncludes;
  177.     }
  178.    
  179.     public String getPackagefilterexcludes() {
  180.         return packageFilterExcludes;
  181.     }

  182.     public void setPackagefilterexcludes(String packageFilterExcludes) {
  183.         this.packageFilterExcludes = packageFilterExcludes;
  184.     }

  185.     public boolean getClassfilter() {
  186.         return classFilter;
  187.     }

  188.     public void setClassfilter(boolean classFilter) {
  189.         this.classFilter = classFilter;
  190.     }
  191.    
  192.     public String getClassfilterincludes() {
  193.         return classFilterIncludes;
  194.     }

  195.     public void setClassfilterincludes(String classFilterIncludes) {
  196.         this.classFilterIncludes = classFilterIncludes;
  197.     }
  198.    
  199.     public String getClassfilterexcludes() {
  200.         return classFilterExcludes;
  201.     }

  202.     public void setClassfilterexcludes(String classFilterExcludes) {
  203.         this.classFilterExcludes = classFilterExcludes;
  204.     }

  205.     public boolean getFeaturefilter() {
  206.         return featureFilter;
  207.     }

  208.     public void setFeaturefilter(boolean featureFilter) {
  209.         this.featureFilter = featureFilter;
  210.     }
  211.    
  212.     public String getFeaturefilterincludes() {
  213.         return featureFilterIncludes;
  214.     }

  215.     public void setFeaturefilterincludes(String featureFilterIncludes) {
  216.         this.featureFilterIncludes = featureFilterIncludes;
  217.     }
  218.    
  219.     public String getFeaturefilterexcludes() {
  220.         return featureFilterExcludes;
  221.     }

  222.     public void setFeaturefilterexcludes(String featureFilterExcludes) {
  223.         this.featureFilterExcludes = featureFilterExcludes;
  224.     }

  225.     public void setP2p(boolean value) {
  226.         setPackagescope(value);
  227.         setPackagefilter(value);
  228.     }
  229.    
  230.     public void setC2p(boolean value) {
  231.         setClassscope(value);
  232.         setPackagefilter(value);
  233.     }

  234.     public void setC2c(boolean value) {
  235.         setClassscope(value);
  236.         setClassfilter(value);
  237.     }

  238.     public void setF2f(boolean value) {
  239.         setFeaturescope(value);
  240.         setFeaturefilter(value);
  241.     }

  242.     public void setIncludes(String value) {
  243.         setScopeincludes(value);
  244.         setFilterincludes(value);
  245.     }

  246.     public void setExcludes(String value) {
  247.         setScopeexcludes(value);
  248.         setFilterexcludes(value);
  249.     }

  250.     public boolean getList() {
  251.         return list;
  252.     }
  253.    
  254.     public void setList(boolean list) {
  255.         this.list = list;
  256.     }

  257.     public boolean getChartclassesperpackage() {
  258.         return chartClassesPerPackage;
  259.     }
  260.    
  261.     public void setChartclassesperpackage(boolean chartClassesPerPackage) {
  262.         this.chartClassesPerPackage = chartClassesPerPackage;
  263.     }

  264.     public boolean getChartfeaturesperclass() {
  265.         return chartFeaturesPerClass;
  266.     }
  267.    
  268.     public void setChartfeaturesperclass(boolean chartFeaturesPerClass) {
  269.         this.chartFeaturesPerClass = chartFeaturesPerClass;
  270.     }

  271.     public boolean getChartinboundsperpackage() {
  272.         return chartInboundsPerPackage;
  273.     }
  274.    
  275.     public void setChartinboundsperpackage(boolean chartInboundsPerPackage) {
  276.         this.chartInboundsPerPackage = chartInboundsPerPackage;
  277.     }

  278.     public boolean getChartoutboundsperpackage() {
  279.         return chartOutboundsPerPackage;
  280.     }
  281.    
  282.     public void setChartoutboundsperpackage(boolean chartOutboundsPerPackage) {
  283.         this.chartOutboundsPerPackage = chartOutboundsPerPackage;
  284.     }

  285.     public boolean getChartinboundsperclass() {
  286.         return chartInboundsPerClass;
  287.     }
  288.    
  289.     public void setChartinboundsperclass(boolean chartInboundsPerClass) {
  290.         this.chartInboundsPerClass = chartInboundsPerClass;
  291.     }

  292.     public boolean getChartoutboundsperclass() {
  293.         return chartOutboundsPerClass;
  294.     }
  295.    
  296.     public void setChartoutboundsperclass(boolean chartOutboundsPerClass) {
  297.         this.chartOutboundsPerClass = chartOutboundsPerClass;
  298.     }
  299.    
  300.     public boolean getChartinboundsperfeature() {
  301.         return chartInboundsPerFeature;
  302.     }
  303.    
  304.     public void setChartinboundsperfeature(boolean chartInboundsPerFeature) {
  305.         this.chartInboundsPerFeature = chartInboundsPerFeature;
  306.     }

  307.     public boolean getChartoutboundsperfeature() {
  308.         return chartOutboundsPerFeature;
  309.     }
  310.    
  311.     public void setChartoutboundsperfeature(boolean chartOutboundsPerFeature) {
  312.         this.chartOutboundsPerFeature = chartOutboundsPerFeature;
  313.     }

  314.     public void setChartinbounds(boolean chartInbounds) {
  315.         setChartinboundsperpackage(chartInbounds);
  316.         setChartinboundsperclass(chartInbounds);
  317.         setChartinboundsperfeature(chartInbounds);
  318.     }

  319.     public void setChartoutbounds(boolean chartOutbounds) {
  320.         setChartoutboundsperpackage(chartOutbounds);
  321.         setChartoutboundsperclass(chartOutbounds);
  322.         setChartoutboundsperfeature(chartOutbounds);
  323.     }

  324.     public void setChartpackages(boolean chartPackages) {
  325.         setChartclassesperpackage(chartPackages);
  326.         setChartinboundsperpackage(chartPackages);
  327.         setChartoutboundsperpackage(chartPackages);
  328.     }

  329.     public void setChartclasses(boolean chartClasses) {
  330.         setChartfeaturesperclass(chartClasses);
  331.         setChartinboundsperclass(chartClasses);
  332.         setChartoutboundsperclass(chartClasses);
  333.     }

  334.     public void setChartfeatures(boolean chartFeatures) {
  335.         setChartinboundsperfeature(chartFeatures);
  336.         setChartoutboundsperfeature(chartFeatures);
  337.     }

  338.     public void setChartall(boolean chartAll) {
  339.         setChartclassesperpackage(chartAll);
  340.         setChartfeaturesperclass(chartAll);
  341.         setChartinboundsperpackage(chartAll);
  342.         setChartoutboundsperpackage(chartAll);
  343.         setChartinboundsperclass(chartAll);
  344.         setChartoutboundsperclass(chartAll);
  345.         setChartinboundsperfeature(chartAll);
  346.         setChartoutboundsperfeature(chartAll);
  347.     }

  348.     public boolean getHistogramclassesperpackage() {
  349.         return histogramClassesPerPackage;
  350.     }

  351.     public void setHistogramclassesperpackage(boolean histogramClassesPerPackage) {
  352.         this.histogramClassesPerPackage = histogramClassesPerPackage;
  353.     }

  354.     public boolean getHistogramfeaturesperclass() {
  355.         return histogramFeaturesPerClass;
  356.     }

  357.     public void setHistogramfeaturesperclass(boolean histogramFeaturesPerClass) {
  358.         this.histogramFeaturesPerClass = histogramFeaturesPerClass;
  359.     }

  360.     public boolean getHistograminboundsperpackage() {
  361.         return histogramInboundsPerPackage;
  362.     }

  363.     public void setHistograminboundsperpackage(boolean histogramInboundsPerPackage) {
  364.         this.histogramInboundsPerPackage = histogramInboundsPerPackage;
  365.     }

  366.     public boolean getHistogramoutboundsperpackage() {
  367.         return histogramOutboundsPerPackage;
  368.     }

  369.     public void setHistogramoutboundsperpackage(boolean histogramOutboundsPerPackage) {
  370.         this.histogramOutboundsPerPackage = histogramOutboundsPerPackage;
  371.     }

  372.     public boolean getHistograminboundsperclass() {
  373.         return histogramInboundsPerClass;
  374.     }

  375.     public void setHistograminboundsperclass(boolean histogramInboundsPerClass) {
  376.         this.histogramInboundsPerClass = histogramInboundsPerClass;
  377.     }

  378.     public boolean getHistogramoutboundsperclass() {
  379.         return histogramOutboundsPerClass;
  380.     }

  381.     public void setHistogramoutboundsperclass(boolean histogramOutboundsPerClass) {
  382.         this.histogramOutboundsPerClass = histogramOutboundsPerClass;
  383.     }

  384.     public boolean getHistograminboundsperfeature() {
  385.         return histogramInboundsPerFeature;
  386.     }

  387.     public void setHistograminboundsperfeature(boolean histogramInboundsPerFeature) {
  388.         this.histogramInboundsPerFeature = histogramInboundsPerFeature;
  389.     }

  390.     public boolean getHistogramoutboundsperfeature() {
  391.         return histogramOutboundsPerFeature;
  392.     }

  393.     public void setHistogramoutboundsperfeature(boolean histogramOutboundsPerFeature) {
  394.         this.histogramOutboundsPerFeature = histogramOutboundsPerFeature;
  395.     }

  396.     public void setHistograminbounds(boolean histogramInbounds) {
  397.         setHistograminboundsperpackage(histogramInbounds);
  398.         setHistograminboundsperclass(histogramInbounds);
  399.         setHistograminboundsperfeature(histogramInbounds);
  400.     }

  401.     public void setHistogramoutbounds(boolean histogramOutbounds) {
  402.         setHistogramoutboundsperpackage(histogramOutbounds);
  403.         setHistogramoutboundsperclass(histogramOutbounds);
  404.         setHistogramoutboundsperfeature(histogramOutbounds);
  405.     }

  406.     public void setHistogrampackages(boolean histogramPackages) {
  407.         setHistogramclassesperpackage(histogramPackages);
  408.         setHistograminboundsperpackage(histogramPackages);
  409.         setHistogramoutboundsperpackage(histogramPackages);
  410.     }

  411.     public void setHistogramclasses(boolean histogramClasses) {
  412.         setHistogramfeaturesperclass(histogramClasses);
  413.         setHistograminboundsperclass(histogramClasses);
  414.         setHistogramoutboundsperclass(histogramClasses);
  415.     }

  416.     public void setHistogramfeatures(boolean histogramFeatures) {
  417.         setHistograminboundsperfeature(histogramFeatures);
  418.         setHistogramoutboundsperfeature(histogramFeatures);
  419.     }

  420.     public void setHistogramall(boolean histogramAll) {
  421.         setHistogramclassesperpackage(histogramAll);
  422.         setHistogramfeaturesperclass(histogramAll);
  423.         setHistograminboundsperpackage(histogramAll);
  424.         setHistogramoutboundsperpackage(histogramAll);
  425.         setHistograminboundsperclass(histogramAll);
  426.         setHistogramoutboundsperclass(histogramAll);
  427.         setHistograminboundsperfeature(histogramAll);
  428.         setHistogramoutboundsperfeature(histogramAll);
  429.     }

  430.     public boolean getJson() {
  431.         return json;
  432.     }

  433.     public void setJson(boolean json) {
  434.         this.json = json;
  435.     }

  436.     public void execute() throws BuildException {
  437.         // first off, make sure that we've got what we need
  438.         validateParameters();

  439.         VerboseListener verboseListener = new VerboseListener(this);

  440.         try {
  441.             NodeFactory factory = new NodeFactory();

  442.             for (String filename : getSrc().list()) {
  443.                 log("Reading graph from " + filename);

  444.                 if (filename.endsWith(".xml")) {
  445.                     NodeLoader loader = new NodeLoader(factory, getValidate());
  446.                     loader.addDependencyListener(verboseListener);
  447.                     loader.load(filename);
  448.                 }
  449.             }

  450.             log("Saving metrics report to " + getDestfile().getAbsolutePath());

  451.             PrintWriter out = new PrintWriter(new FileWriter(getDestfile()));

  452.             MetricsReport reporter;
  453.             if (getJson()) {
  454.                 reporter = new JSONMetricsReport(out);
  455.             } else {
  456.                 reporter = new TextMetricsReport(out);
  457.             }

  458.             reporter.setListingElements(getList());

  459.             reporter.setShowingClassesPerPackageChart(getChartclassesperpackage());
  460.             reporter.setShowingFeaturesPerClassChart(getChartfeaturesperclass());
  461.             reporter.setShowingInboundsPerPackageChart(getChartinboundsperpackage());
  462.             reporter.setShowingOutboundsPerPackageChart(getChartoutboundsperpackage());
  463.             reporter.setShowingInboundsPerClassChart(getChartinboundsperclass());
  464.             reporter.setShowingOutboundsPerClassChart(getChartoutboundsperclass());
  465.             reporter.setShowingInboundsPerFeatureChart(getChartinboundsperfeature());
  466.             reporter.setShowingOutboundsPerFeatureChart(getChartoutboundsperfeature());

  467.             reporter.setShowingClassesPerPackageHistogram(getHistogramclassesperpackage());
  468.             reporter.setShowingFeaturesPerClassHistogram(getHistogramfeaturesperclass());
  469.             reporter.setShowingInboundsPerPackageHistogram(getHistograminboundsperpackage());
  470.             reporter.setShowingOutboundsPerPackageHistogram(getHistogramoutboundsperpackage());
  471.             reporter.setShowingInboundsPerClassHistogram(getHistograminboundsperclass());
  472.             reporter.setShowingOutboundsPerClassHistogram(getHistogramoutboundsperclass());
  473.             reporter.setShowingInboundsPerFeatureHistogram(getHistograminboundsperfeature());
  474.             reporter.setShowingOutboundsPerFeatureHistogram(getHistogramoutboundsperfeature());

  475.             MetricsGatherer metrics = new MetricsGatherer(getStrategy());
  476.             metrics.traverseNodes(factory.getPackages().values());
  477.             reporter.process(metrics);

  478.             out.close();
  479.         } catch (SAXException | ParserConfigurationException | IOException ex) {
  480.             throw new BuildException(ex);
  481.         }
  482.     }

  483.     private SelectionCriteria getScopeCriteria() throws BuildException {
  484.         RegularExpressionSelectionCriteria result = new RegularExpressionSelectionCriteria();

  485.         if (getPackagescope() || getClassscope() || getFeaturescope()) {
  486.             result.setMatchingPackages(getPackagescope());
  487.             result.setMatchingClasses(getClassscope());
  488.             result.setMatchingFeatures(getFeaturescope());
  489.         }

  490.         result.setGlobalIncludes(getScopeincludes());
  491.         result.setGlobalExcludes(getScopeexcludes());
  492.         result.setPackageIncludes(getPackagescopeincludes());
  493.         result.setPackageExcludes(getPackagescopeexcludes());
  494.         result.setClassIncludes(getClassscopeincludes());
  495.         result.setClassExcludes(getClassscopeexcludes());
  496.         result.setFeatureIncludes(getFeaturescopeincludes());
  497.         result.setFeatureExcludes(getFeaturescopeexcludes());

  498.         return result;
  499.     }

  500.     private SelectionCriteria getFilterCriteria() throws BuildException {
  501.         RegularExpressionSelectionCriteria result = new RegularExpressionSelectionCriteria();

  502.         if (getPackagefilter() || getClassfilter() || getFeaturefilter()) {
  503.             result.setMatchingPackages(getPackagefilter());
  504.             result.setMatchingClasses(getClassfilter());
  505.             result.setMatchingFeatures(getFeaturefilter());
  506.         }

  507.         result.setGlobalIncludes(getFilterincludes());
  508.         result.setGlobalExcludes(getFilterexcludes());
  509.         result.setPackageIncludes(getPackagefilterincludes());
  510.         result.setPackageExcludes(getPackagefilterexcludes());
  511.         result.setClassIncludes(getClassfilterincludes());
  512.         result.setClassExcludes(getClassfilterexcludes());
  513.         result.setFeatureIncludes(getFeaturefilterincludes());
  514.         result.setFeatureExcludes(getFeaturefilterexcludes());

  515.         return result;
  516.     }
  517.    
  518.     private TraversalStrategy getStrategy() throws BuildException {
  519.         return new SelectiveTraversalStrategy(getScopeCriteria(), getFilterCriteria());
  520.     }
  521. }