Project Report: fawkez

Packagesummary org.jcoderz.phoenix.report

org.jcoderz.phoenix.report.StatisticCollector

LineHitsNoteSource
1  /*
2   * $Id: StatisticCollector.java 1454 2009-05-10 11:06:43Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.phoenix.report;
34  
35  import java.awt.Color;
36  import java.awt.Dimension;
37  import java.io.FileWriter;
38  import java.io.IOException;
39  import java.util.HashMap;
40  import java.util.Iterator;
41  import java.util.List;
42  import java.util.Map;
43  import java.util.Set;
44  import java.util.TreeSet;
45  import java.util.Map.Entry;
46  
47  import net.sourceforge.chart2d.Chart2DProperties;
48  import net.sourceforge.chart2d.Dataset;
49  import net.sourceforge.chart2d.GraphChart2DProperties;
50  import net.sourceforge.chart2d.GraphProperties;
51  import net.sourceforge.chart2d.LBChart2D;
52  import net.sourceforge.chart2d.LegendProperties;
53  import net.sourceforge.chart2d.MultiColorsProperties;
54  import net.sourceforge.chart2d.Object2DProperties;
55  
56  import org.jcoderz.commons.util.IoUtil;
57  import org.jcoderz.commons.util.ObjectUtil;
58  import org.jcoderz.phoenix.report.jaxb.File;
59  import org.jcoderz.phoenix.report.jaxb.Report;
60  
61  /**
62 (1) * TODO: Extend this class to run historic tool on existing reports.
63   *
64   * @author Andreas Mandel
65   */
66  public final class StatisticCollector
67  {
68     private static final int MAX_SERVICE_PACKAGES = 15;
69     private static final int ROW_ERROR = 0;
70     private static final int ROW_CPD = 1;
71     private static final int ROW_WARNING = 2;
72     private static final int ROW_DESIGN = 3;
73     private static final int ROW_CODE_STYLE = 4;
74     private static final int ROW_INFO = 5;
75     private static final int ROW_COVERAGE = 6;
76     private static final int PERCENT = 100;
77     private static final int LARGE_IMAGE_WIDTH = 1000;
78     private static final int LARGE_IMAGE_HEIGHT = 600;
79     private static final int SMALL_IMAGE_WIDTH = 800;
80     private static final int SMALL_IMAGE_HEIGHT = 300;
810    private static final Dimension LARGE_SIZE
82           = new Dimension(LARGE_IMAGE_WIDTH, LARGE_IMAGE_HEIGHT);
830    private static final Dimension SMALL_SIZE
84           = new Dimension(SMALL_IMAGE_WIDTH, SMALL_IMAGE_HEIGHT);
85  
86     /** The report to be used as input. */
87     private final Report mReport;
88  
89     /** The package prefix to check for. */
90     private final String mPrefix;
91  
92     /** The dir to be used as output. */
93     private final java.io.File mOutDir;
94  
95     /** The timestamp when the report was initiated. */
96     private final String mTimestamp;
97  
98  
99     /**
100      * Creates a new StatisticCollector object.
101      *
102      * @param report the input report.
103      * @param outDir the output dir for the charts and summary xml.
104      * @param timestamp the timestamp for the summary db entry.
105      */
106     public StatisticCollector (Report report, java.io.File outDir,
107           String timestamp)
1080    {
1090       mReport = report;
110 (2)      // TODO: Try to find this automagically, 2 - 3 packagelevels
1110       mPrefix = "org.jcoderz.";
1120       mOutDir = outDir;
1130       mTimestamp = timestamp;
1140    }
115  
116     /**
117      * Creates a new StatisticCollector object.
118      *
119      * @param report the input report.
120      * @param prefix the package prefix
121      * @param outDir the output dir for the charts and summary xml.
122      * @param timestamp the timestamp for the summary db entry.
123      */
124     public StatisticCollector (Report report, String prefix, java.io.File outDir,
125           String timestamp)
1260    {
1270       mReport = report;
1280       mPrefix = prefix;
1290       mOutDir = outDir;
1300       mTimestamp = timestamp;
1310    }
132  
133     /**
134      * Creates the charts.
135      * @throws IOException if the image can not be written.
136      */
137     public void createCharts ()
138           throws IOException
139     {
140        // chart should contain x axis with packages,
141        // y axis with number of lines
142        // (2 lines 1 for production code one for test code)
143  
1440       final Map<String, FileSummary> productionPackages
145            = new HashMap<String, FileSummary>();
1460       final Map<String, FileSummary> testPackages
147            = new HashMap<String, FileSummary>();
1480       final Map<String, FileSummary> allPackages
149            = new HashMap<String, FileSummary>();
150  
1510       summarize(productionPackages, testPackages, allPackages);
152  
1530       writeSummary(allPackages);
154  
1550       allPackages.clear(); // make GC happy
156  
157        final Map<String, FileSummary> production;
158        final Map<String, FileSummary> test;
159        final String level;
160  
1610       if (productionPackages.size() > MAX_SERVICE_PACKAGES)
162        {
1630          production = generateServiceLevelMap(productionPackages);
1640          test = generateServiceLevelMap(testPackages);
1650          level = "Service";
166        }
167        else
168        {
1690          production = productionPackages;
1700          test = testPackages;
1710          level = "Package";
172        }
173  
1740       createLocChart(production, test, level);
175  
1760       createQualityChart(production, level);
1770    }
178  
179     /**
180      * Writes a summary xml for the given summary map.
181      * @param packages a map with the package names / summaries to be
182      *       used.
183      * @throws IOException if the XML file can not be written
184      */
185     private void writeSummary (Map<String, FileSummary> packages)
186           throws IOException
187     {
1880(3)      final StringBuffer sb = new StringBuffer();
189  
190  
1910       final FileSummary all = new FileSummary();
1920       final Iterator<FileSummary> i = packages.values().iterator();
193  
1940       while (i.hasNext())
195        {
1960          all.add(i.next());
197        }
198  
1990       sb.append("<findingsummary ");
2000       fillSummaryLine(sb, all);
2010       sb.append(">\n");
202  
2030       sb.append(" <packagelevelxml>\n");
2040       for (Entry<String, FileSummary> entry : packages.entrySet())
205        {
2060          final String pkg = entry.getKey();
2070          final FileSummary summary = entry.getValue();
2080          sb.append(" <package name='");
2090          sb.append(pkg);
2100          sb.append("' ");
2110          fillSummaryLine(sb, summary);
2120          sb.append("/>\n");
2130       }
2140       sb.append(" </packagelevelxml>\n");
215  
216  
2170       final Map<String, FileSummary> serviceLevelMap
218            = generateServiceLevelMap(packages);
219  
220  
2210       sb.append(" <servicelevelxml>\n");
2220       for (Entry<String, FileSummary> service : serviceLevelMap.entrySet())
223        {
2240          final String pkg = service.getKey();
2250          final FileSummary summary = service.getValue();
2260          sb.append(" <service name='");
2270          sb.append(pkg);
2280          sb.append("' ");
2290          fillSummaryLine(sb, summary);
2300          sb.append("/>\n");
2310       }
2320       sb.append(" </servicelevelxml>\n");
233  
2340       sb.append("</findingsummary>\n");
235  
2360       FileWriter w = null;
237        try
238        {
2390          final java.io.File out = new java.io.File(mOutDir, "summary.xml");
2400          w = new FileWriter(out);
2410          w.write(sb.toString());
242        }
243        finally
244        {
2450           IoUtil.close(w);
2460       }
2470    }
248  
249     private Map<String, FileSummary> generateServiceLevelMap (
250         Map<String, FileSummary> packages)
251     {
2520       final Map<String, FileSummary> serviceLevelMap
253            = new HashMap<String, FileSummary>();
254  
2550       for (Entry<String, FileSummary> packagz : packages.entrySet())
256        {
2570          final String pkg = packagz.getKey();
2580          final FileSummary summary = packagz.getValue();
2590          final String service = getService(pkg);
260  
2610          FileSummary serviceSummary = serviceLevelMap.get(service);
2620          if (serviceSummary == null)
263           {
2640             serviceSummary = new FileSummary(service);
2650             serviceLevelMap.put(service, serviceSummary);
266           }
2670          serviceSummary.add(summary);
2680       }
2690       return serviceLevelMap;
270     }
271  
272     private void fillSummaryLine (final StringBuffer sb, FileSummary summary)
273     {
2740       sb.append("timestamp='");
2750       sb.append(mTimestamp);
2760       sb.append("' ");
2770       for (int i = 0; i < Severity.VALUES.size(); i++)
278        {
2790           final Severity currentSeverity = Severity.fromInt(i);
2800           sb.append(currentSeverity.toString());
2810           sb.append("='");
2820           sb.append(summary.getViolations(currentSeverity));
2830           sb.append("' ");
284        }
2850       sb.append(" loc='");
2860       sb.append(summary.getLinesOfCode());
2870       sb.append("' codeLoc='");
2880       sb.append(summary.getCoverage()
289            + summary.getViolations(Severity.COVERAGE));
2900       sb.append("' quality='");
2910       sb.append(summary.getQualityAsFloat());
2920       sb.append('\'');
2930    }
294  
295     private String getService (String pkg)
296     {
297        String result;
2980       if (pkg != null && pkg.startsWith(mPrefix))
299        {
3000          result = pkg.substring(mPrefix.length());
3010          if (result.indexOf('.') != -1)
302           {
3030             result = result.substring(result.indexOf('.') + 1);
304           }
3050          if (result.indexOf('.') != -1)
306           {
3070             result = result.substring(0, result.indexOf('.'));
308           }
309        }
310        else
311        {
3120          result = ObjectUtil.toStringOrEmpty(pkg);
313        }
3140       return result;
315     }
316  
317     /**
318      * Collects summary data and puts the results in the given maps.
319      * @param productionPackages map to collect production code data.
320      * @param testPackages map to collect test code data.
321      * @param all All packages.
322      */
323     private void summarize (final Map<String, FileSummary> productionPackages,
324           final Map<String, FileSummary> testPackages,
325           final Map<String, FileSummary> all)
326     {
3270(4)      final List<File> allFiles = mReport.getFile();
3280       for (final File currentFile : allFiles)
329        {
330           // Level 3 is currently given to test classes, below 3 is production
3310          if (currentFile.getLevel().equals(ReportLevel.TEST))
332           {
3330             addToMap(testPackages, currentFile);
3340             addToMap(all, currentFile);
335           }
336           else
337           {
3380             addToMap(productionPackages, currentFile);
3390             addToMap(all, currentFile);
340           }
341        }
3420    }
343  
344     private FileSummary addToMap (final Map<String, FileSummary> map,
345         final File file)
346     {
3470       final String pkg = file.getPackage();
3480       FileSummary counter = map.get(pkg);
3490       if (counter == null)
350        {
3510          counter = new FileSummary(pkg);
3520          map.put(pkg, counter);
353        }
3540       calculateSummary(file, counter);
3550       return counter;
356     }
357  
358     /**
359      * Collects finding summary for a concrete file.
360      * @param currentFile the file structure.
361      * @param counter the counter structure.
362      */
363     private void calculateSummary (File currentFile, FileSummary counter)
364     {
3650        counter.add(currentFile);
3660    }
367  
368     /**
369      * Creates the lines of code chart.
370      * Locs are painted per package. Separated by test and production code.
371      * The output is a "loc.png".
372      *
373      * @throws IOException if the image can not be written.
374      */
375     private void createLocChart (Map<String, FileSummary> src,
376         Map<String, FileSummary> test, String level)
377           throws IOException
378     {
379       //<-- Begin Chart2D configuration -->
380  
381       //Configure object properties
3820      final Object2DProperties object2DProps = new Object2DProperties();
3830      object2DProps.setObjectTitleText ("LOC by " + level);
384  
385       //Configure chart properties
3860      final Chart2DProperties chart2DProps = new Chart2DProperties();
3870      chart2DProps.setChartDataLabelsPrecision (1);
388  
389       //Configure legend properties
3900      final LegendProperties legendProps = new LegendProperties();
3910(5)     final String[] legendLabels = {"Production", "Test"};
3920      legendProps.setLegendLabelsTexts (legendLabels);
393  
394       //Configure graph chart properties
3950      final GraphChart2DProperties graphChart2DProps
396               = new GraphChart2DProperties();
397  
3980      final Set<String> labels = new TreeSet<String>(src.keySet());
3990      labels.addAll(test.keySet());
400  
4010      if (labels.size() == 0)
402       {
4030(6)        throw new RuntimeException("No packages found for chart!");
404       }
405  
4060(7)     final String [] labelsLongAxisLabels
407             = labels.toArray(new String[]{});
4080      final String [] labelsAxisLabels
409             = cutPackages(labelsLongAxisLabels);
410  
4110      graphChart2DProps.setLabelsAxisLabelsTexts(labelsAxisLabels);
4120      graphChart2DProps.setLabelsAxisTitleText(level + " Name");
4130      graphChart2DProps.setNumbersAxisTitleText("LOC");
4140      graphChart2DProps.setLabelsAxisTicksAlignment(
415             GraphChart2DProperties.CENTERED);
416  
417       //Configure graph properties
4180      final GraphProperties graphProps = new GraphProperties();
4190      graphProps.setGraphBarsExistence(false);
4200      graphProps.setGraphDotsExistence(true);
4210      graphProps.setGraphAllowComponentAlignment(true);
4220      graphProps.setGraphDotsWithinCategoryOverlapRatio(1);
423  
424       //Configure dataset
4250      final Dataset dataset = new Dataset (legendLabels.length,
426             labelsAxisLabels.length, 1);
427  
428       // fill data....
4290      for (int j = 0; j < dataset.getNumCats(); ++j)
430       {
4310         dataset.set(0, j, 0, getCounter(src, labelsLongAxisLabels[j]));
4320         dataset.set(1, j, 0, getCounter(test, labelsLongAxisLabels[j]));
433       }
434  
435       //Configure graph component colors
4360      final MultiColorsProperties multiColorsProps
437           = new MultiColorsProperties();
438  
439       //Configure chart
4400      final LBChart2D chart2D = new LBChart2D();
4410      chart2D.setObject2DProperties (object2DProps);
4420      chart2D.setChart2DProperties (chart2DProps);
4430      chart2D.setLegendProperties (legendProps);
4440      chart2D.setGraphChart2DProperties (graphChart2DProps);
4450      chart2D.addGraphProperties (graphProps);
4460      chart2D.addDataset (dataset);
4470      chart2D.addMultiColorsProperties (multiColorsProps);
448  
449       //<-- End Chart2D configuration -->
450  
451  
4520      chart2D.setMaximumSize(LARGE_SIZE);
4530      chart2D.setPreferredSize(LARGE_SIZE);
454  
4550      if (chart2D.validate(false))
456       {
4570         java.io.File file = new java.io.File(mOutDir, "loc_large.png");
4580         javax.imageio.ImageIO.write(chart2D.getImage(), "PNG", file);
4590         chart2D.setMaximumSize(SMALL_SIZE);
4600         chart2D.setPreferredSize(SMALL_SIZE);
4610         chart2D.pack();
4620         file = new java.io.File(mOutDir, "loc_small.png");
4630         javax.imageio.ImageIO.write(chart2D.getImage(), "PNG", file);
4640      }
465       else
466       {
4670         chart2D.validate(true);
468       }
4690    }
470  
471     /**
472      * Creates the quality chart.
473      * The output is a "quality.png".
474      *
475      * @throws IOException if the image can not be written.
476      */
477 (8)   private void createQualityChart (Map<String, FileSummary> src, String level)
478           throws IOException
479     {
480       //<-- Begin Chart2D configuration -->
481  
482       //Configure object properties
4830      final Object2DProperties object2DProps = new Object2DProperties();
4840      object2DProps.setObjectTitleText ("Quality by " + level);
485  
486       //Configure chart properties
4870      final Chart2DProperties chart2DProps = new Chart2DProperties();
4880      chart2DProps.setChartDataLabelsPrecision(0);
489  
490       //Configure legend properties
4910      final LegendProperties legendProps = new LegendProperties();
4920(9)     final String[] legendLabels = {
493           "Error", "C&P", "Warning", "Design", "Code Style",
494           "Info", "Coverage"};
4950      legendProps.setLegendLabelsTexts (legendLabels);
496  
497       //Configure graph chart properties
4980      final GraphChart2DProperties graphChart2DProps
499               = new GraphChart2DProperties();
500  
5010      final Set<String> labels = new TreeSet<String>(src.keySet());
502  
5030      if (labels.size() == 0)
504       {
5050(10)        throw new RuntimeException("No packages found for chart!");
506       }
507  
5080      final String [] labelsLongAxisLabels
509             = labels.toArray(new String[labels.size()]);
5100      final String [] labelsAxisLabels = cutPackages(labelsLongAxisLabels);
511  
5120      graphChart2DProps.setLabelsAxisLabelsTexts(labelsAxisLabels);
5130      graphChart2DProps.setLabelsAxisTitleText(level + " Name");
5140      graphChart2DProps.setNumbersAxisTitleText("Finding/Loc %");
5150      graphChart2DProps.setLabelsAxisTicksAlignment(
516             GraphChart2DProperties.CENTERED);
517  
518       //Configure graph properties
5190      final GraphProperties graphProps = new GraphProperties();
5200      graphProps.setGraphBarsExistence(false);
5210      graphProps.setGraphDotsExistence(true);
5220      graphProps.setGraphAllowComponentAlignment(true);
5230      graphProps.setGraphDotsWithinCategoryOverlapRatio(1);
524  
525       //Configure dataset
5260      final Dataset dataset = new Dataset (legendLabels.length,
527             labelsAxisLabels.length, 1);
528  
529       // fill data....
5300      for (int j = 0; j < dataset.getNumCats(); ++j)
531       {
5320         final FileSummary sum = src.get(labelsLongAxisLabels[j]);
5330         if (sum != null && sum.getLinesOfCode() != 0)
534          {
5350            final float loc = sum.getLinesOfCode();
5360            final float codeLoc = sum.getCoverage()
537                 + sum.getViolations(Severity.COVERAGE);
538  
5390            dataset.set(ROW_ERROR, j, 0,
540                 (PERCENT * sum.getViolations(Severity.ERROR)) / loc);
5410            dataset.set(ROW_CPD, j, 0,
542                 (PERCENT * sum.getViolations(Severity.CPD)) / loc);
5430            dataset.set(ROW_WARNING, j, 0,
544                 (PERCENT * sum.getViolations(Severity.WARNING)) / loc);
5450            dataset.set(ROW_DESIGN, j, 0,
546                 (PERCENT * sum.getViolations(Severity.DESIGN)) / loc);
5470            dataset.set(ROW_CODE_STYLE, j, 0,
548                 (PERCENT * sum.getViolations(Severity.CODE_STYLE)) / loc);
5490            dataset.set(ROW_INFO, j, 0,
550                 (PERCENT * sum.getViolations(Severity.INFO)) / loc);
551  
5520            if (codeLoc != 0)
553             {
5540               dataset.set(ROW_COVERAGE, j, 0,
555                      (PERCENT * sum.getCoverage()) / codeLoc);
556             }
557             else
558             {
5590               dataset.set(ROW_COVERAGE, j, 0, PERCENT);
560             }
5610         }
562          else
563          {
5640            dataset.set(ROW_ERROR, j, 0, 0);
5650            dataset.set(ROW_CPD, j, 0, 0);
5660            dataset.set(ROW_WARNING, j, 0, 0);
5670            dataset.set(ROW_DESIGN, j, 0, 0);
5680            dataset.set(ROW_CODE_STYLE, j, 0, 0);
5690            dataset.set(ROW_INFO, j, 0, 0);
5700            dataset.set(ROW_COVERAGE, j, 0, 0);
571          }
572       }
573  
574       //Configure graph component colors
5750      final MultiColorsProperties multiColorsProps
576               = new MultiColorsProperties();
577  
5780      multiColorsProps.setColorsCustomize(true);
579  
5800      multiColorsProps.setColorsCustom(new Color[]
581             {
582                Color.RED,
583                Color.BLUE,
584                Color.ORANGE,
585                Color.YELLOW,
586                Color.YELLOW,
587                Color.CYAN,
588                Color.MAGENTA
589             });
590  
591       //Configure chart
5920      final LBChart2D chart2D = new LBChart2D();
5930      chart2D.setObject2DProperties (object2DProps);
5940      chart2D.setChart2DProperties (chart2DProps);
5950      chart2D.setLegendProperties (legendProps);
5960      chart2D.setGraphChart2DProperties (graphChart2DProps);
5970      chart2D.addGraphProperties (graphProps);
5980      chart2D.addDataset (dataset);
5990      chart2D.addMultiColorsProperties (multiColorsProps);
600  
601       //<-- End Chart2D configuration -->
602  
6030      chart2D.setMaximumSize(LARGE_SIZE);
6040      chart2D.setPreferredSize(LARGE_SIZE);
605  
6060      if (chart2D.validate(false))
607       {
6080         java.io.File file = new java.io.File(mOutDir, "quality_large.png");
6090         javax.imageio.ImageIO.write(chart2D.getImage(), "PNG", file);
6100         chart2D.setMaximumSize(SMALL_SIZE);
6110         chart2D.setPreferredSize(SMALL_SIZE);
6120         chart2D.pack();
6130         file = new java.io.File(mOutDir, "quality_small.png");
6140         javax.imageio.ImageIO.write(chart2D.getImage(), "PNG", file);
6150      }
616       else
617       {
6180         chart2D.validate(true);
619       }
6200    }
621  
622     /**
623      * Gets the loc counter for a given package.
624      */
625     private float getCounter (Map<String, FileSummary> src,
626         String string)
627     {
6280       final FileSummary counter = src.get(string);
629        final int result;
630  
6310       if (counter != null)
632        {
6330          result = counter.getLinesOfCode();
634        }
635        else
636        {
6370          result = 0;
638        }
6390       return result;
640     }
641  
642     /**
643      * Returns an array with the short for of the given package name.
644      * @param labelsAxisLabels an array with package names to be cut.
645      * @return a string array containing short form of the input package names.
646      */
647     private String[] cutPackages (String[] labelsAxisLabels)
648     {
6490       final String [] result = new String[labelsAxisLabels.length];
650  
6510       for (int i = 0; i < labelsAxisLabels.length; i++)
652        {
6530          if (labelsAxisLabels[i].startsWith(mPrefix))
654           {
6550             result[i]
656                    = labelsAxisLabels[i].substring(mPrefix.length());
6570             if (result[i].indexOf('.') != -1)
658              {
6590                result[i] = result[i].substring(result[i].indexOf('.') + 1);
660              }
661           }
662           else
663           {
6640(11)            result[i] = labelsAxisLabels[i];
665           }
666        }
667  
6680       return result;
669     }
670  
671  }

Findings in this File

i (1) 62 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (2) 110 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (3) 188 : 0 method org.jcoderz.phoenix.report.StatisticCollector.writeSummary(Map) creates local variable-based synchronized collection
d (4) 327 : 50 [unchecked] unchecked conversion found : java.util.List required: java.util.List<org.jcoderz.phoenix.report.jaxb.File>
i (5) 391 : 0 Method org.jcoderz.phoenix.report.StatisticCollector.createLocChart(Map, Map, String) creates array using constants
i (6) 403 : 0 method org.jcoderz.phoenix.report.StatisticCollector.createLocChart(Map, Map, String) throws exception with static message string
i (7) 406 : 0 Method org.jcoderz.phoenix.report.StatisticCollector.createLocChart(Map, Map, String) uses Collection.toArray() with zero-length array argument
d (8) 477 : 4 Method length is 142 lines (max allowed is 100).
w (9) 492 : 0 Method org.jcoderz.phoenix.report.StatisticCollector.createQualityChart(Map, String) creates array using constants
i (10) 505 : 0 method org.jcoderz.phoenix.report.StatisticCollector.createQualityChart(Map, String) throws exception with static message string
w (11) 664 : 0 method org.jcoderz.phoenix.report.StatisticCollector.cutPackages(String[]) copies arrays manually