Coverage Report - net.sf.statsvn.output.RepoMapPageMaker
 
Classes in this File Line Coverage Branch Coverage Complexity
RepoMapPageMaker
0%
0/129
0%
0/56
3
 
 1  
 /*
 2  
  StatSVN - SVN Subversion statistics generation
 3  
  Copyright (C) 2006 Benoit Xhenseval
 4  
  http://www.statsvn.org
 5  
 
 6  
  This library is free software; you can redistribute it and/or
 7  
  modify it under the terms of the GNU Lesser General Public
 8  
  License as published by the Free Software Foundation; either
 9  
  version 2.1 of the License, or (at your option) any later version.
 10  
 
 11  
  This library is distributed in the hope that it will be useful,
 12  
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  
  Lesser General Public License for more details.
 15  
 
 16  
  You should have received a copy of the GNU Lesser General Public
 17  
  License along with this library; if not, write to the Free Software
 18  
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 19  
 
 20  
  */
 21  
 package net.sf.statsvn.output;
 22  
 
 23  
 import java.io.BufferedWriter;
 24  
 import java.io.File;
 25  
 import java.io.FileWriter;
 26  
 import java.io.IOException;
 27  
 import java.io.InputStream;
 28  
 import java.io.Writer;
 29  
 import java.util.Calendar;
 30  
 import java.util.Date;
 31  
 import java.util.Iterator;
 32  
 import java.util.SortedSet;
 33  
 
 34  
 import net.sf.statcvs.Messages;
 35  
 import net.sf.statcvs.model.Directory;
 36  
 import net.sf.statcvs.model.Revision;
 37  
 import net.sf.statcvs.model.VersionedFile;
 38  
 import net.sf.statcvs.output.ConfigurationOptions;
 39  
 import net.sf.statcvs.output.ReportConfig;
 40  
 import net.sf.statcvs.pages.HTML;
 41  
 import net.sf.statcvs.pages.NavigationNode;
 42  
 import net.sf.statcvs.pages.Page;
 43  
 import net.sf.statcvs.util.FileUtils;
 44  
 
 45  
 /**
 46  
  * New report that Repo Map, a jtreemap-based report (applet) that shows the
 47  
  * entire source tree in a hierarchical manner, the size of each box is related
 48  
  * to LOC and the colour to the changes over the last 30 days (red -loc, green
 49  
  * +loc).
 50  
  *
 51  
  * @author Benoit Xhenseval (www.objectlab.co.uk)
 52  
  * @see http://jtreemap.sourceforge.net for more about JTreeMap.
 53  
  */
 54  
 public class RepoMapPageMaker {
 55  
         private static final int DAYS_FROM_LAST_DATE = 30;
 56  
 
 57  
         private static final String WEB_FILE_PATH = "web-files/";
 58  
 
 59  
         private static final String REPO_FILE = "repomap-data.txt";
 60  
 
 61  
         private final Date deadline;
 62  
         
 63  
         private final Date currentDate;
 64  
 
 65  
         private final ReportConfig config;
 66  
 
 67  0
         private int indent = 0;
 68  
 
 69  
         /**
 70  
          * @see net.sf.statcvs.output.HTMLPage#HTMLPage(Repository)
 71  
          */
 72  0
         public RepoMapPageMaker(final ReportConfig config) {
 73  0
                 final Calendar cal = Calendar.getInstance();
 74  0
                 if (config !=null && config.getRepository() != null && config.getRepository().getLastDate()!=null) {
 75  0
                         cal.setTime(config.getRepository().getLastDate());
 76  
                 }
 77  0
                 currentDate = cal.getTime();
 78  0
                 cal.add(Calendar.DATE, -DAYS_FROM_LAST_DATE);
 79  0
                 deadline = cal.getTime();
 80  0
                 this.config = config;
 81  0
         }
 82  
 
 83  
         public NavigationNode toFile() {
 84  0
                 final Page page = this.config.createPage("repomap", Messages.getString("REPOMAP_TITLE"), Messages.getString("REPOMAP_TITLE"));
 85  0
                 page.addRawAttribute(Messages.getString("REPOMAP_START_DATE"), HTML.getDate(deadline));
 86  0
                 page.addRawAttribute(Messages.getString("REPOMAP_END_DATE"), HTML.getDate(currentDate));
 87  
 
 88  0
                 page.addRawContent("<p>" + Messages.getString("REPOMAP_DESCRIPTION") + "</p>");
 89  0
                 page.addRawContent("<p>" + getApplet() + "</p>");
 90  0
                 page.addRawContent("<p><small>This page uses <a href=\"http://jtreemap.sourceforge.net\">JTreeMap</a>.</small></p>");
 91  0
                 buildXmlForJTreeMap();
 92  
 
 93  0
                 return page;
 94  
         }
 95  
 
 96  
         private String getApplet() {
 97  0
                 return "<applet archive=\"./" + Messages.getString("JTREEMAP_JAR") + "\" code=\"net.sf.jtreemap.swing.example.JTreeMapAppletExample\""
 98  
                         + " width=\"940\" height=\"600\"><param name=\"dataFile\" value=\"" + REPO_FILE + "\"/>" + "<param name=\"viewTree\" value=\"true\"/>"
 99  
                         + "<param name=\"showWeight\" value=\"true\"/>" + "<param name=\"valuePrefix\" value=\"Change:\"/>"
 100  
                         + "<param name=\"weightPrefix\" value=\"LOC:\"/>" + "<param name=\"dataFileType\" value=\"xml\"/>"
 101  
                         + "<param name=\"colorProvider\" value=\"HSBLog\"/>" + "</applet>";
 102  
         }
 103  
 
 104  
         private void buildXmlForJTreeMap() {
 105  0
                 BufferedWriter out = null;
 106  
                 try {
 107  0
                         copyJar(Messages.getString("JTREEMAP_JAR"));
 108  0
                         out = new BufferedWriter(new FileWriter(ConfigurationOptions.getOutputDir() + REPO_FILE));
 109  0
                         out.write("<?xml version='1.0' encoding='ISO-8859-1'?>\n");
 110  
                         // out.append("<!DOCTYPE root SYSTEM \"TreeMap.dtd\" >\n");
 111  0
                         out.write("<root>\n");
 112  0
                         final Iterator it = config.getRepository().getDirectories().iterator();
 113  0
                         if (it.hasNext()) {
 114  0
                                 final Directory dir = (Directory) it.next();
 115  0
                                 doDirectory(out, dir);
 116  
                         }
 117  0
                         out.write("</root>");
 118  0
                 } catch (final IOException e) {
 119  0
                         e.printStackTrace();
 120  
                 } finally {
 121  0
                         if (out != null) {
 122  
                                 try {
 123  0
                                         out.close();
 124  0
                                 } catch (final IOException e) {
 125  0
                                         SvnConfigurationOptions.getTaskLogger().error(e.toString());
 126  0
                                 }
 127  
                         }
 128  
                 }
 129  0
         }
 130  
 
 131  
         private void copyJar(final String jtreemapJar) throws IOException {
 132  0
                 InputStream stream = null;
 133  
                 try {
 134  0
                         stream = RepoMapPageMaker.class.getResourceAsStream(WEB_FILE_PATH + jtreemapJar);
 135  0
                         if (stream != null) {
 136  0
                                 FileUtils.copyFile(stream, new File(ConfigurationOptions.getOutputDir() + jtreemapJar));
 137  
                         } else {
 138  0
                                 throw new IOException("The stream to " + (WEB_FILE_PATH + jtreemapJar) + " failed, is it copied in the jar?");
 139  
                         }
 140  
                 } finally {
 141  0
                         if (stream != null) {
 142  0
                                 stream.close();
 143  
                         }
 144  
                 }
 145  0
         }
 146  
 
 147  
         private void addSpaces(final int count, final BufferedWriter out) throws IOException {
 148  0
                 out.write(getSpaces(count));
 149  0
         }
 150  
 
 151  
         private String getSpaces(final int count) {
 152  0
                 final StringBuffer result = new StringBuffer();
 153  0
                 for (int i = 0; i < count; i++) {
 154  0
                         result.append("  ");
 155  
                 }
 156  0
                 return result.toString();
 157  
         }
 158  
 
 159  
         private void doDirectory(final BufferedWriter out, final Directory dir) throws IOException {
 160  0
                 indent++;
 161  0
                 SvnConfigurationOptions.getTaskLogger().log("Directory:" + getSpaces(indent) + dir.getName());
 162  
 
 163  0
                 if (dir.isEmpty()) {
 164  0
                         indent--;
 165  0
                         return;
 166  
                 }
 167  
 
 168  0
                 final SortedSet set = dir.getSubdirectories();
 169  0
                 final SortedSet files = dir.getFiles();
 170  0
                 final String name = dir.isRoot() ? Messages.getString("NAVIGATION_ROOT") : dir.getName();
 171  0
                 boolean addedBranch = false;
 172  0
                 if (indent > 1 && set != null && !set.isEmpty()) {
 173  0
                         out.write("\n");
 174  0
                         addSpaces(indent, out);
 175  0
                         out.write("<branch>\n");
 176  0
                         addSpaces(indent + 2, out);
 177  0
                         labelTag(out, name);
 178  0
                         addedBranch = true;
 179  0
                 } else if (indent == 1) {
 180  0
                         addSpaces(indent, out);
 181  0
                         labelTag(out, name);
 182  
                 }
 183  0
                 if (set != null) {
 184  0
                         for (final Iterator it2 = set.iterator(); it2.hasNext();) {
 185  0
                                 doDirectory(out, (Directory) it2.next());
 186  
                         }
 187  
                 }
 188  0
                 addedBranch = handleEachFileInDir(out, files, name, addedBranch);
 189  0
                 if (addedBranch) {
 190  0
                         addSpaces(indent, out);
 191  0
                         out.write("</branch>\n");
 192  
                 }
 193  0
                 indent--;
 194  0
         }
 195  
 
 196  
         private boolean handleEachFileInDir(final BufferedWriter out, final SortedSet files, final String name, boolean addedBranch) throws IOException {
 197  0
                 if (files != null && !files.isEmpty()) {
 198  0
                         for (final Iterator file = files.iterator(); file.hasNext();) {
 199  0
                                 final VersionedFile vfile = (VersionedFile) file.next();
 200  
 
 201  0
                                 int loc = vfile.getCurrentLinesOfCode();
 202  
 
 203  0
                                 SvnConfigurationOptions.getTaskLogger().log("File:" + vfile.getFilename() + " LOC:" + loc);
 204  
 
 205  0
                                 int delta = calculateTotalDelta(vfile);
 206  0
                                 if (loc == 0) {
 207  0
                                         loc = Math.abs(delta);
 208  
                                 }
 209  0
                                 if (loc == 0) {
 210  0
                                         continue;
 211  
                                 }
 212  0
                                 if (!addedBranch) {
 213  0
                                         out.write("\n");
 214  0
                                         addSpaces(indent, out);
 215  0
                                         out.write("<branch>\n");
 216  0
                                         addSpaces(indent + 2, out);
 217  0
                                         labelTag(out, name);
 218  0
                                         out.write("\n");
 219  0
                                         addedBranch = true;
 220  
                                 }
 221  0
                                 addSpaces(indent + 2, out);
 222  0
                                 out.write("<leaf>");
 223  0
                                 labelTag(out, vfile.getFilename());
 224  0
                                 tag(out, "weight", String.valueOf(loc));
 225  0
                                 final double percentage = ((double) delta) / (double) loc * 100.0;
 226  0
                                 tag(out, "value", String.valueOf(percentage));
 227  0
                                 out.write("</leaf>\n");
 228  0
                                 SvnConfigurationOptions.getTaskLogger().log("===========>>> LOC=" + loc + " totalDelta=" + delta + " Delta%=" + percentage);
 229  0
                         }
 230  
                 }
 231  0
                 return addedBranch;
 232  
         }
 233  
 
 234  
         private int calculateTotalDelta(final VersionedFile vfile) {
 235  0
                 int delta = 0;
 236  0
                 final SortedSet revisions = vfile.getRevisions();
 237  
                 // take all deltas for the last 30 days.
 238  0
                 for (final Iterator rev = revisions.iterator(); rev.hasNext();) {
 239  0
                         final Revision revision = (Revision) rev.next();
 240  
 
 241  0
                         SvnConfigurationOptions.getTaskLogger().log(
 242  
                                 "Revision " + revision.getDate() + " file:" + vfile.getFilename() + " Dead:" + vfile.isDead() + " LOC:" + revision.getLines() + " delta:"
 243  
                                         + revision.getLinesDelta());
 244  
 
 245  0
                         if (deadline.before(revision.getDate())) {
 246  0
                                 delta += revision.getLinesDelta();
 247  
 
 248  0
                                 SvnConfigurationOptions.getTaskLogger().log(
 249  
                                         "Revision " + revision.getRevisionNumber() + " Delta:" + revision.getLinesDelta() + " totalDelta:" + delta + " LOC:"
 250  
                                                 + revision.getLines() + " Dead:" + revision.isDead());
 251  
                         }
 252  0
                 }
 253  0
                 return delta;
 254  
         }
 255  
 
 256  
         private void labelTag(final Writer result, final String name) throws IOException {
 257  0
                 if (name == null || name.length() == 0) {
 258  0
                         tag(result, "label", "[root]");
 259  
                 } else {
 260  0
                         tag(result, "label", name);
 261  
                 }
 262  0
         }
 263  
 
 264  
         private void tag(final Writer result, final String tagName, final String value) throws IOException {
 265  0
                 result.write("<");
 266  0
                 result.write(tagName);
 267  0
                 result.write(">");
 268  0
                 result.write(value);
 269  0
                 result.write("</");
 270  0
                 result.write(tagName);
 271  0
                 result.write(">");
 272  0
         }
 273  
 }