Coverage Report - net.sf.statcvs.charts.LOCChartMaker
 
Classes in this File Line Coverage Branch Coverage Complexity
LOCChartMaker
0%
0/104
0%
0/72
3.13
LOCChartMaker$1
0%
0/19
0%
0/10
3.13
LOCChartMaker$2
0%
0/8
0%
0/4
3.13
LOCChartMaker$AllDevelopersLOCChartMaker
0%
0/54
0%
0/50
3.13
LOCChartMaker$AllDirectoriesLOCChartMaker
0%
0/94
0%
0/80
3.13
LOCChartMaker$AllDirectoriesLOCChartMaker$1
0%
0/22
0%
0/14
3.13
LOCChartMaker$AllModulesLOCChartMaker
0%
0/49
0%
0/22
3.13
LOCChartMaker$AllModulesLOCChartMaker$1
0%
0/8
0%
0/4
3.13
LOCChartMaker$DirectoryLOCChartMaker
0%
0/15
0%
0/16
3.13
LOCChartMaker$MainLOCChartMaker
0%
0/7
N/A
3.13
 
 1  
 package net.sf.statcvs.charts;
 2  
 
 3  
 import java.awt.Color;
 4  
 import java.awt.Dimension;
 5  
 import java.awt.Paint;
 6  
 import java.util.ArrayList;
 7  
 import java.util.Collection;
 8  
 import java.util.Collections;
 9  
 import java.util.Comparator;
 10  
 import java.util.Date;
 11  
 import java.util.HashMap;
 12  
 import java.util.Iterator;
 13  
 import java.util.List;
 14  
 import java.util.Map;
 15  
 import java.util.SortedSet;
 16  
 
 17  
 import net.sf.statcvs.Messages;
 18  
 import net.sf.statcvs.model.Author;
 19  
 import net.sf.statcvs.model.Directory;
 20  
 import net.sf.statcvs.model.Module;
 21  
 import net.sf.statcvs.model.Repository;
 22  
 import net.sf.statcvs.model.Revision;
 23  
 import net.sf.statcvs.output.ReportConfig;
 24  
 import net.sf.statcvs.pages.HTML;
 25  
 import net.sf.statcvs.reports.LOCSeriesBuilder;
 26  
 import net.sf.statcvs.util.IntegerMap;
 27  
 
 28  
 import org.jfree.chart.ChartFactory;
 29  
 import org.jfree.chart.JFreeChart;
 30  
 import org.jfree.chart.annotations.XYAnnotation;
 31  
 import org.jfree.chart.axis.DateAxis;
 32  
 import org.jfree.chart.axis.ValueAxis;
 33  
 import org.jfree.chart.plot.XYPlot;
 34  
 import org.jfree.chart.renderer.xy.XYItemRenderer;
 35  
 import org.jfree.chart.renderer.xy.XYStepRenderer;
 36  
 import org.jfree.data.time.TimeSeries;
 37  
 import org.jfree.data.time.TimeSeriesCollection;
 38  
 
 39  
 /**
 40  
  * Produces Lines Of Code charts
 41  
  * 
 42  
  * TODO: At least the single-series charts should be done by TimeLineChartMakers
 43  
  * 
 44  
  * @author jentzsch
 45  
  * @author Richard Cyganiak (richard@cyganiak.de)
 46  0
  * @version $Id: LOCChartMaker.java,v 1.19 2009/08/31 19:16:35 benoitx Exp $
 47  0
  */
 48  0
 public class LOCChartMaker {
 49  0
     private final ReportConfig config;
 50  0
     private ChartImage chartFile = null;
 51  
     private final String chartName;
 52  
 
 53  
     /**
 54  
      * Creates a Lines Of Code chart from a <tt>BasicTimeSeries</tt> and
 55  
      * saves it as PNG
 56  
      * @param locSeries the LOC history
 57  
      * @param title the chart title
 58  
      * @param fileName the filename where the chart will be saved
 59  
      * @param size width and height of PNG in pixels
 60  0
      * @param annotations
 61  0
      */
 62  0
     public LOCChartMaker(final String chartName, final ReportConfig config, final TimeSeries locSeries, final String title, final String fileName,
 63  0
             final Dimension size, final List annotations) {
 64  0
         this.chartName = chartName;
 65  0
         this.config = config;
 66  0
         if (locSeries == null) {
 67  0
             return;
 68  0
         }
 69  0
         final Paint[] colors = new Paint[1];
 70  0
         colors[0] = Color.RED;
 71  0
 
 72  0
         final TimeSeriesCollection collection = new TimeSeriesCollection();
 73  0
         collection.addSeries(locSeries);
 74  0
         final JFreeChart chart = createLOCChart(collection, colors, title, annotations);
 75  0
         final Dimension dim = ChartConfigUtil.getDimension(chartName, size);
 76  0
         this.chartFile = this.config.createChartImage(fileName, title, chart, dim);
 77  0
     }
 78  
 
 79  
     /**
 80  
      * Creates a Lines Of Code chart from a list of <tt>BasicTimesSeries</tt> and
 81  
      * saves it as PNG
 82  
      * @param locSeriesList a list of <tt>BasicTimesSeries</tt>
 83  0
      * @param title the chart title
 84  0
      * @param fileName the filename where the chart will be saved
 85  0
      * @param size width and height of PNG in pixels
 86  0
      */
 87  0
     public LOCChartMaker(final String chartName, final ReportConfig config, final List locSeriesList, final String title, final String fileName,
 88  0
             final Dimension size, final List annotations) {
 89  0
         this.chartName = chartName;
 90  0
         this.config = config;
 91  0
         if (locSeriesList.isEmpty()) {
 92  0
             return;
 93  0
         }
 94  0
         int i = 0;
 95  0
         final TimeSeriesCollection collection = new TimeSeriesCollection();
 96  0
         final Iterator it = locSeriesList.iterator();
 97  0
         while (it.hasNext()) {
 98  0
             final TimeSeries series = (TimeSeries) it.next();
 99  0
             collection.addSeries(series);
 100  0
             i++;
 101  0
         }
 102  0
         final JFreeChart chart = createLOCChart(collection, null, title, annotations);
 103  0
         final Dimension dim = ChartConfigUtil.getDimension(chartName, size);
 104  0
 
 105  0
         this.chartFile = this.config.createChartImage(fileName, title, chart, dim);
 106  0
     }
 107  0
 
 108  0
     private JFreeChart createLOCChart(final TimeSeriesCollection data, final Paint[] colors, final String title, final List annotations) {
 109  0
         final String domain = Messages.getString("TIME_LOC_DOMAIN");
 110  0
         final String range = Messages.getString("TIME_LOC_RANGE");
 111  0
 
 112  0
         final boolean legend = (data.getSeriesCount() > 1);
 113  0
         final JFreeChart chart = ChartFactory.createTimeSeriesChart(this.config.getProjectName() + ": " + title, domain, range, data, legend, false, false);
 114  0
 
 115  0
         final XYPlot plot = chart.getXYPlot();
 116  0
         plot.setRenderer(new XYStepRenderer());
 117  0
         if (colors == null) {
 118  0
             // We don't like the bright yellow color early on in the series, use a darker one
 119  0
             for (int i = 0; i < plot.getSeriesCount(); i++) {
 120  0
                 final Paint seriesPaint = plot.getRenderer().getSeriesPaint(i);
 121  0
                 if (seriesPaint != null && seriesPaint.equals(new Color(0xFF, 0xFF, 0x55))) {
 122  0
                     plot.getRenderer().setSeriesPaint(i, new Color(240, 220, 0x55));
 123  0
                 }
 124  0
             }
 125  0
         } else {
 126  0
             for (int i = 0; i < colors.length; i++) {
 127  0
                 plot.getRenderer().setSeriesPaint(i, colors[i]);
 128  0
             }
 129  0
         }
 130  0
         final DateAxis domainAxis = (DateAxis) plot.getDomainAxis();
 131  0
         domainAxis.setVerticalTickLabels(true);
 132  0
         final ValueAxis valueAxis = plot.getRangeAxis();
 133  0
         valueAxis.setLowerBound(0);
 134  0
 
 135  0
         if (annotations != null) {
 136  0
             for (final Iterator it = annotations.iterator(); it.hasNext();) {
 137  0
                 plot.addAnnotation((XYAnnotation) it.next());
 138  
             }
 139  
         }
 140  0
 
 141  0
         plot.setBackgroundPaint(ChartConfigUtil.getPlotColor(chartName));
 142  0
         chart.setBackgroundPaint(ChartConfigUtil.getBackgroundColor(chartName));
 143  0
         final XYItemRenderer renderer = plot.getRenderer();
 144  0
         ChartConfigUtil.configureStroke(chartName, renderer, data);
 145  0
         ChartConfigUtil.configureShapes(chartName, renderer);
 146  0
         ChartConfigUtil.configureCopyrightNotice(chartName, chart);
 147  0
         ChartConfigUtil.configureChartBackgroungImage(chartName, chart);
 148  0
         ChartConfigUtil.configurePlotImage(chartName, chart);
 149  0
 
 150  0
         return chart;
 151  0
     }
 152  
 
 153  0
     public ChartImage toFile() {
 154  0
         return this.chartFile;
 155  0
     }
 156  0
 
 157  0
     private static TimeSeries getLOCTimeSeries(final SortedSet revisions, final String title) {
 158  0
         final LOCSeriesBuilder locCounter = new LOCSeriesBuilder(title, true);
 159  0
         final Iterator it = revisions.iterator();
 160  0
         while (it.hasNext()) {
 161  0
             locCounter.addRevision((Revision) it.next());
 162  0
         }
 163  0
         if (locCounter.getMaximum() == 0) {
 164  0
             return null;
 165  0
         }
 166  0
         return locCounter.getTimeSeries();
 167  
     }
 168  0
 
 169  
     public static class MainLOCChartMaker extends LOCChartMaker {
 170  0
         public MainLOCChartMaker(final String chartName, final ReportConfig config, final String fileName, final Dimension size) {
 171  0
             super(chartName, config, getLOCTimeSeries(config.getRepository().getRevisions(), Messages.getString("TIME_LOC_SUBTITLE")), Messages
 172  0
                     .getString("TIME_LOC_SUBTITLE"), fileName, size, SymbolicNameAnnotation.createAnnotations(config.getRepository().getSymbolicNames()));
 173  0
         }
 174  
     }
 175  0
 
 176  0
     public static class DirectoryLOCChartMaker extends LOCChartMaker {
 177  0
         private static String getTitle(final Directory directory) {
 178  0
             return directory.getPath() + (directory.getPath() != null && directory.getPath().length() > 1 ? " " : "") + Messages.getString("TIME_LOC_SUBTITLE");
 179  0
         }
 180  0
 
 181  0
         private static String getFilename(final Directory directory) {
 182  0
             return "loc_module" + HTML.escapeDirectoryName(directory.getPath()) + ".png";
 183  0
         }
 184  0
 
 185  0
         public DirectoryLOCChartMaker(final ReportConfig config, final Directory directory) {
 186  0
             super("loc_module", config, getLOCTimeSeries(directory.getRevisions(), getTitle(directory)), getTitle(directory), getFilename(directory), config
 187  0
                     .getLargeChartSize(), SymbolicNameAnnotation.createAnnotations(config.getRepository().getSymbolicNames()));
 188  0
         }
 189  
     }
 190  0
 
 191  0
     public static class AllDevelopersLOCChartMaker extends LOCChartMaker {
 192  0
         private static List createAllDevelopersLOCSeries(final ReportConfig config) {
 193  0
             Iterator it = config.getRepository().getAuthors().iterator();
 194  0
             final Map authorSeriesMap = new HashMap();
 195  0
             while (it.hasNext()) {
 196  0
                 final Author author = (Author) it.next();
 197  0
                 if (!config.isDeveloper(author)) {
 198  0
                     continue;
 199  0
                 }
 200  0
                 authorSeriesMap.put(author, new LOCSeriesBuilder(author.getRealName(), false));
 201  0
             }
 202  0
             it = config.getRepository().getRevisions().iterator();
 203  0
             while (it.hasNext()) {
 204  0
                 final Revision rev = (Revision) it.next();
 205  0
                 if (rev.isBeginOfLog()) {
 206  0
                     continue;
 207  0
                 }
 208  0
                 final LOCSeriesBuilder builder = (LOCSeriesBuilder) authorSeriesMap.get(rev.getAuthor());
 209  0
                 if (builder != null) {
 210  0
                     builder.addRevision(rev);
 211  0
                 } // otherwise the revision was by a non-developer login
 212  0
             }
 213  0
             final List authors = new ArrayList(authorSeriesMap.keySet());
 214  0
             Collections.sort(authors);
 215  0
             final List result = new ArrayList();
 216  0
             it = authors.iterator();
 217  0
             while (it.hasNext()) {
 218  0
                 final Author author = (Author) it.next();
 219  0
                 final LOCSeriesBuilder builder = (LOCSeriesBuilder) authorSeriesMap.get(author);
 220  0
                 final TimeSeries series = builder.getTimeSeries();
 221  0
                 if (series != null) {
 222  0
                     result.add(series);
 223  0
                 }
 224  0
             }
 225  0
             return result;
 226  0
         }
 227  0
 
 228  0
         public AllDevelopersLOCChartMaker(final ReportConfig config, final Dimension size) {
 229  0
             super("loc_per_author", config, createAllDevelopersLOCSeries(config), Messages.getString("CONTRIBUTED_LOC_TITLE"), "loc_per_author.png", size,
 230  0
                     SymbolicNameAnnotation.createAnnotations(config.getRepository().getSymbolicNames()));
 231  0
         }
 232  0
     }
 233  0
 
 234  0
     public static class AllDirectoriesLOCChartMaker extends LOCChartMaker {
 235  0
         private static Collection getMajorDirectories(final Repository repository, final int max) {
 236  0
             if (repository.getFirstDate() == null || repository.getLastDate() == null || repository.getFirstDate().equals(repository.getLastDate())) {
 237  0
                 return Collections.EMPTY_LIST;
 238  0
             }
 239  0
             final IntegerMap importances = new IntegerMap();
 240  0
             final Iterator it = repository.getDirectories().iterator();
 241  0
             while (it.hasNext()) {
 242  0
                 final Directory directory = (Directory) it.next();
 243  0
                 importances.put(directory, getImportance(directory, repository.getFirstDate(), repository.getLastDate()));
 244  0
             }
 245  0
             final List result = new ArrayList(repository.getDirectories());
 246  0
             Collections.sort(result, new Comparator() {
 247  0
                 public int compare(final Object o1, final Object o2) {
 248  0
                     final int importance1 = importances.get(o1);
 249  0
                     final int importance2 = importances.get(o2);
 250  0
                     if (importance1 > importance2) {
 251  0
                         return -1;
 252  0
                     }
 253  0
                     if (importance1 == importance2) {
 254  0
                         return 0;
 255  0
                     }
 256  0
                     return 1;
 257  
                 }
 258  0
             });
 259  0
             return firstN(result, max);
 260  0
         }
 261  0
 
 262  0
         private static int getImportance(final Directory dir, final Date start, final Date end) {
 263  0
             final long timeRange = end.getTime() - start.getTime();
 264  0
             double maxImportance = 0;
 265  0
             int currentLines = 0;
 266  0
             final Iterator it = dir.getRevisions().iterator();
 267  0
             while (it.hasNext()) {
 268  0
                 final Revision revision = (Revision) it.next();
 269  0
                 currentLines += revision.getLinesDelta();
 270  0
                 final long timeInRange = revision.getDate().getTime() - start.getTime();
 271  0
                 final double timeFraction = (timeInRange / (double) timeRange) * 0.9 + 0.1;
 272  0
                 maxImportance = Math.max(maxImportance, (currentLines) * (timeFraction));
 273  0
             }
 274  0
             return (int) (maxImportance * 10);
 275  0
         }
 276  0
 
 277  0
         private static List firstN(final List list, final int n) {
 278  0
             return list.subList(0, Math.min(list.size(), n));
 279  0
         }
 280  0
 
 281  0
         private static List createAllDirectoriesLOCSeries(final Repository repository, final int max) {
 282  0
             Iterator it = getMajorDirectories(repository, max).iterator();
 283  0
             final Map directorySeriesMap = new HashMap();
 284  0
             while (it.hasNext()) {
 285  0
                 final Directory directory = (Directory) it.next();
 286  0
                 directorySeriesMap.put(directory, new LOCSeriesBuilder(directory.getPath(), true));
 287  0
             }
 288  0
             it = repository.getRevisions().iterator();
 289  0
             while (it.hasNext()) {
 290  0
                 final Revision rev = (Revision) it.next();
 291  0
                 if (rev.isBeginOfLog()) {
 292  0
                     continue;
 293  0
                 }
 294  0
                 final LOCSeriesBuilder builder = (LOCSeriesBuilder) directorySeriesMap.get(rev.getFile().getDirectory());
 295  0
                 if (builder == null) {
 296  0
                     continue; // minor directory
 297  0
                 }
 298  0
                 builder.addRevision(rev);
 299  0
             }
 300  0
             final List directories = new ArrayList(directorySeriesMap.keySet());
 301  0
             Collections.sort(directories);
 302  0
             final List result = new ArrayList();
 303  0
             it = directories.iterator();
 304  0
             while (it.hasNext()) {
 305  0
                 final Directory directory = (Directory) it.next();
 306  0
                 final LOCSeriesBuilder builder = (LOCSeriesBuilder) directorySeriesMap.get(directory);
 307  0
                 final TimeSeries series = builder.getTimeSeries();
 308  0
                 if (series != null) {
 309  0
                     result.add(series);
 310  0
                 }
 311  0
             }
 312  0
             return result;
 313  0
         }
 314  
 
 315  0
         public AllDirectoriesLOCChartMaker(final ReportConfig config, final int showMaxDirectories) {
 316  0
             super("directories_loc_timeline", config, createAllDirectoriesLOCSeries(config.getRepository(), showMaxDirectories), Messages
 317  
                     .getString("DIRECTORY_LOC_TITLE"), "directories_loc_timeline.png", config.getLargeChartSize(), SymbolicNameAnnotation
 318  0
                     .createAnnotations(config.getRepository().getSymbolicNames()));
 319  0
         }
 320  
     }
 321  
 
 322  
 
 323  
     public static class AllModulesLOCChartMaker extends LOCChartMaker {
 324  
         private static Collection getMajorModules(final Repository repository, final int max) {
 325  0
             if (repository.getFirstDate() == null || repository.getLastDate() == null || repository.getFirstDate().equals(repository.getLastDate())) {
 326  0
                 return Collections.EMPTY_LIST;
 327  
             }
 328  0
             final IntegerMap importances = new IntegerMap();
 329  0
             final Iterator it = repository.getModules().values().iterator();
 330  0
             while (it.hasNext()) {
 331  0
                 final Module directory = (Module) it.next();
 332  0
                 importances.put(directory, getImportance(directory, repository.getFirstDate(), repository.getLastDate()));
 333  
             }
 334  0
             final List result = new ArrayList(repository.getModules().values());
 335  0
             Collections.sort(result, new Comparator() {
 336  0
                 public int compare(final Object o1, final Object o2) {
 337  0
                     final int importance1 = importances.get(o1);
 338  0
                     final int importance2 = importances.get(o2);
 339  0
                     if (importance1 > importance2) {
 340  0
                         return -1;
 341  
                     }
 342  0
                     if (importance1 == importance2) {
 343  0
                         return 0;
 344  
                     }
 345  0
                     return 1;
 346  
                 }
 347  
             });
 348  0
             return firstN(result, max);
 349  
         }
 350  
 
 351  
         private static int getImportance(final Module dir, final Date start, final Date end) {
 352  0
             final long timeRange = end.getTime() - start.getTime();
 353  0
             double maxImportance = 0;
 354  0
             int currentLines = 0;
 355  0
             final Iterator it = dir.getRevisions().iterator();
 356  0
             while (it.hasNext()) {
 357  0
                 final Revision revision = (Revision) it.next();
 358  0
                 currentLines += revision.getLinesDelta();
 359  0
                 final long timeInRange = revision.getDate().getTime() - start.getTime();
 360  0
                 final double timeFraction = (timeInRange / (double) timeRange) * 0.9 + 0.1;
 361  0
                 maxImportance = Math.max(maxImportance, (currentLines) * (timeFraction));
 362  
             }
 363  0
             return (int) (maxImportance * 10);
 364  
         }
 365  
 
 366  
         private static List firstN(final List list, final int n) {
 367  0
             return list.subList(0, Math.min(list.size(), n));
 368  
         }
 369  
 
 370  
         private static List createAllModulesLOCSeries(final Repository repository, final int max) {
 371  0
             Iterator it = getMajorModules(repository, max).iterator();
 372  0
             final Map directorySeriesMap = new HashMap();
 373  0
             while (it.hasNext()) {
 374  0
                 final Module module = (Module) it.next();
 375  0
                 directorySeriesMap.put(module, new LOCSeriesBuilder(module.getName(), true));
 376  
             }
 377  0
             it = repository.getRevisions().iterator();
 378  0
             while (it.hasNext()) {
 379  0
                 final Revision rev = (Revision) it.next();
 380  0
                 if (rev.isBeginOfLog()) {
 381  0
                     continue;
 382  
                 }
 383  0
                 final LOCSeriesBuilder builder = (LOCSeriesBuilder) directorySeriesMap.get(rev.getFile().getModule());
 384  0
                 if (builder == null) {
 385  0
                     continue; // minor directory
 386  
                 }
 387  0
                 builder.addRevision(rev);
 388  
             }
 389  0
             final List modules = new ArrayList(directorySeriesMap.keySet());
 390  0
             Collections.sort(modules);
 391  0
             final List result = new ArrayList();
 392  0
             it = modules.iterator();
 393  0
             while (it.hasNext()) {
 394  0
                 final Module module = (Module) it.next();
 395  0
                 final LOCSeriesBuilder builder = (LOCSeriesBuilder) directorySeriesMap.get(module);
 396  0
                 final TimeSeries series = builder.getTimeSeries();
 397  0
                 if (series != null) {
 398  0
                     result.add(series);
 399  
                 }
 400  
             }
 401  0
             return result;
 402  
         }
 403  
 
 404  
         public AllModulesLOCChartMaker(final ReportConfig config, final int showMaxModules) {
 405  0
             super("modules_loc_timeline", config, createAllModulesLOCSeries(config.getRepository(), showMaxModules), Messages
 406  
                     .getString("MODULES_LOC_TITLE"), "modules_loc_timeline.png", config.getLargeChartSize(), SymbolicNameAnnotation
 407  
                     .createAnnotations(config.getRepository().getSymbolicNames()));
 408  0
         }
 409  
     }
 410  
 }