net.sf.statcvs.output.xml.chart.LocChart.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.statcvs.output.xml.chart.LocChart.java

Source

/*
StatCvs - CVS statistics generation 
Copyright (C) 2002  Lukasz Pekacki <lukasz@pekacki.de>
http://statcvs.sf.net/
    
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
    
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
   $RCSfile: LocChart.java,v $
   $Date: 2003/12/05 12:52:55 $ 
*/
package net.sf.statcvs.output.xml.chart;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import net.sf.statcvs.I18n;
import net.sf.statcvs.model.Author;
import net.sf.statcvs.model.CvsContent;
import net.sf.statcvs.model.CvsRevision;
import net.sf.statcvs.model.Directory;
import net.sf.statcvs.model.RevisionIterator;
import net.sf.statcvs.model.RevisionSortIterator;
import net.sf.statcvs.output.xml.document.AuthorDocument;
import net.sf.statcvs.output.xml.document.ModuleDocument;
import net.sf.statcvs.util.IntegerMap;

import org.jfree.chart.annotations.XYLineAnnotation;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RefineryUtilities;

/**
 * LocChart
 * 
 * @author Tammo van Lessen
 */
public class LocChart extends TimeLineChart {
    private Map tagMap = new HashMap();

    public LocChart(CvsContent content) {
        super("globalloc.png", I18n.tr("Lines Of Code"));
        addTimeLine(calculate(content.getRevisionIterator()));
        setupLocChart();
        getChart().setLegend(null);
    }

    public LocChart(CvsContent content, Directory dir) {
        super("loc" + ModuleDocument.escapeModuleName(dir) + ".png",
                I18n.tr("Lines Of Code for {0}", dir.toString()));

        if (dir.getCurrentFileCount() == 0) {
            setChart(null);
            return;
        }

        TimeLine locTL = calculate(dir.getRevisionIterator());
        locTL.addTimePoint(content.getFirstDate(), 0);
        locTL.addTimePoint(content.getLastDate(), dir.getCurrentLOC());
        addTimeLine(locTL);
        setupLocChart();
        getChart().setLegend(null);
    }

    public LocChart(CvsContent content, Author author) {
        super("loc_per_author.png", I18n.tr("Lines Of Code (per Author)"));

        // init timelines per author
        Iterator authorsIt = content.getAuthors().iterator();
        Map authorTimeLineMap = new HashMap();
        IntegerMap authorsLoc = new IntegerMap();
        while (authorsIt.hasNext()) {
            Author aut = (Author) authorsIt.next();
            TimeLine locTL = new TimeLine(aut.getName());
            locTL.setInitialValue(0);
            authorTimeLineMap.put(aut, locTL);
        }

        // fill timelines and symbolic names map
        RevisionIterator allRevs = new RevisionSortIterator(content.getRevisionIterator());
        while (allRevs.hasNext()) {
            CvsRevision rev = allRevs.next();
            updateSymbolicNamesMap(rev);
            TimeLine timeline = (TimeLine) authorTimeLineMap.get(rev.getAuthor());
            if (!rev.getFile().isBinary()) {
                authorsLoc.addInt(rev.getAuthor(), rev.getLinesOfCodeChange());
                timeline.addTimePoint(rev.getDate(), authorsLoc.get(rev.getAuthor()));
            }
        }

        // create chart
        Iterator it = authorTimeLineMap.keySet().iterator();
        int i = 0;
        while (it.hasNext()) {
            Author aut = (Author) it.next();
            addTimeLine((TimeLine) authorTimeLineMap.get(aut));
            if (author != null) {
                setFilename("loc_" + AuthorDocument.escapeAuthorName(author.getName()) + ".png");
                // make line thicker
                if (author.equals(aut)) {
                    getChart().getXYPlot().getRenderer().setSeriesStroke(i,
                            new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
                }
            }
            i++;
        }
        setupLocChart();
    }

    private void setupLocChart() {
        setRangeLabel(I18n.tr("Lines"));
        makeTagAnnotations();
        placeTitle();
    }

    private TimeLine calculate(RevisionIterator rit) {
        int loc = 0;
        TimeLine locTL = new TimeLine(null);
        RevisionIterator it = new RevisionSortIterator(rit);
        while (it.hasNext()) {
            CvsRevision rev = (CvsRevision) it.next();
            updateSymbolicNamesMap(rev);
            if (!rev.getFile().isBinary()) {

                loc += rev.getLinesOfCodeChange();
                //loc = rev.getEffectiveLinesOfCode();
            }
            locTL.addTimePoint(rev.getDate(), loc);
        }
        return locTL;
    }

    private void updateSymbolicNamesMap(CvsRevision rev) {
        String[] symnames = rev.getSymbolicNames();
        if (symnames.length != 0) {
            for (int i = 0; i < symnames.length; i++) {
                Date lastDate = (Date) tagMap.get(symnames[i]);
                if ((lastDate == null) || (lastDate.before(rev.getDate()))) {
                    tagMap.put(symnames[i], rev.getDate());
                }
            }
        }
    }

    private void makeTagAnnotations() {
        XYPlot xyplot = getChart().getXYPlot();
        Iterator tagIt = tagMap.keySet().iterator();
        while (tagIt.hasNext()) {
            String tag = (String) tagIt.next();
            Date date = (Date) tagMap.get(tag);

            double x = date.getTime();
            double y1 = xyplot.getRangeAxis().getMinimumAxisValue();
            double y2 = xyplot.getRangeAxis().getMaximumAxisValue();
            xyplot.addAnnotation(new TagAnnotation(tag, x, y1, y2));
        }
    }

    private class TagAnnotation extends XYLineAnnotation {

        private double x;
        private double y;
        private String tag;

        public TagAnnotation(String tag, double x, double y1, double y2) {
            super(x, y1, x, y2, new BasicStroke(1.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f,
                    new float[] { 3.5f }, 0.0f), Color.GRAY);
            this.tag = tag;
            this.x = x;
            this.y = y2;
        }

        /**
         * @see org.jfree.chart.annotations.XYAnnotation#draw(java.awt.Graphics2D, java.awt.geom.Rectangle2D, org.jfree.chart.axis.ValueAxis, org.jfree.chart.axis.ValueAxis)
         */
        public void draw(Graphics2D g2, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis) {
            super.draw(g2, getChart().getXYPlot(), dataArea, domainAxis, rangeAxis);

            Font font = new Font("SansSerif", Font.PLAIN, 9);
            FontRenderContext frc = g2.getFontRenderContext();
            Rectangle2D labelBounds = font.getStringBounds(tag, frc);
            // TODO Check why font metric calculation works not properly 
            float baseX = (float) domainAxis.translateValueToJava2D(this.x, dataArea, RectangleEdge.BOTTOM) - 2;
            float baseY = (float) rangeAxis.translateValueToJava2D(y, dataArea, RectangleEdge.LEFT)
                    + (float) labelBounds.getMaxX() + 14;
            g2.setPaint(Color.DARK_GRAY);
            RefineryUtilities.drawRotatedString(tag, g2, baseX, baseY, -Math.PI / 2);
        }
    }
}