Coverage Report - net.sourceforge.cobertura.reporting.xml.XMLReport
 
Classes in this File Line Coverage Branch Coverage Complexity
XMLReport
100%
155/155
95%
21/22
1.524
 
 1  
 /*
 2  
  * Cobertura - http://cobertura.sourceforge.net/
 3  
  *
 4  
  * Copyright (C) 2003 jcoverage ltd.
 5  
  * Copyright (C) 2005 Mark Doliner
 6  
  * Copyright (C) 2005 Jeremy Thomerson
 7  
  * Copyright (C) 2006 Jiri Mares
 8  
  *
 9  
  * Cobertura is free software; you can redistribute it and/or modify
 10  
  * it under the terms of the GNU General Public License as published
 11  
  * by the Free Software Foundation; either version 2 of the License,
 12  
  * or (at your option) any later version.
 13  
  *
 14  
  * Cobertura is distributed in the hope that it will be useful, but
 15  
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 16  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 17  
  * General Public License for more details.
 18  
  *
 19  
  * You should have received a copy of the GNU General Public License
 20  
  * along with Cobertura; if not, write to the Free Software
 21  
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 22  
  * USA
 23  
  */
 24  
 
 25  
 package net.sourceforge.cobertura.reporting.xml;
 26  
 
 27  
 import java.io.File;
 28  
 import java.io.IOException;
 29  
 import java.io.PrintWriter;
 30  
 import java.util.Collection;
 31  
 import java.util.Date;
 32  
 import java.util.Iterator;
 33  
 import java.util.SortedSet;
 34  
 import java.util.TreeSet;
 35  
 
 36  
 import net.sourceforge.cobertura.coveragedata.ClassData;
 37  
 import net.sourceforge.cobertura.coveragedata.JumpData;
 38  
 import net.sourceforge.cobertura.coveragedata.LineData;
 39  
 import net.sourceforge.cobertura.coveragedata.PackageData;
 40  
 import net.sourceforge.cobertura.coveragedata.ProjectData;
 41  
 import net.sourceforge.cobertura.coveragedata.SourceFileData;
 42  
 import net.sourceforge.cobertura.coveragedata.SwitchData;
 43  
 import net.sourceforge.cobertura.reporting.ComplexityCalculator;
 44  
 import net.sourceforge.cobertura.util.FileFinder;
 45  
 import net.sourceforge.cobertura.util.Header;
 46  
 import net.sourceforge.cobertura.util.IOUtil;
 47  
 import net.sourceforge.cobertura.util.StringUtil;
 48  
 
 49  
 import org.apache.log4j.Logger;
 50  
 
 51  
 public class XMLReport
 52  
 {
 53  
 
 54  5
         private static final Logger logger = Logger.getLogger(XMLReport.class);
 55  
 
 56  
         protected final static String coverageDTD = "coverage-03.dtd";
 57  
 
 58  
         private final PrintWriter pw;
 59  
         private final FileFinder finder;
 60  
         private final ComplexityCalculator complexity;
 61  5
         private int indent = 0;
 62  
 
 63  
         public XMLReport(ProjectData projectData, File destinationDir,
 64  
                         FileFinder finder, ComplexityCalculator complexity) throws IOException
 65  5
         {
 66  5
                 this.complexity = complexity;
 67  5
                 this.finder = finder;
 68  
 
 69  5
                 File file = new File(destinationDir, "coverage.xml");
 70  5
                 pw = IOUtil.getPrintWriter(file);
 71  
 
 72  
                 try
 73  
                 {
 74  5
                         println("<?xml version=\"1.0\"?>");
 75  5
                         println("<!DOCTYPE coverage SYSTEM \"http://cobertura.sourceforge.net/xml/"
 76  
                                         + coverageDTD + "\">");
 77  5
                         println("");
 78  
 
 79  
                         // TODO: Set a schema?
 80  
                         //println("<coverage " + sourceDirectories.toString() + " xmlns=\"http://cobertura.sourceforge.net\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://cobertura.sourceforge.net/xml/coverage.xsd\">");
 81  5
                         println("<coverage line-rate=\""
 82  
                                         + projectData.getLineCoverageRate() + "\" branch-rate=\""
 83  
                                         + projectData.getBranchCoverageRate() + "\" version=\""
 84  
                                         + Header.version() + "\" timestamp=\""
 85  
                                         + new Date().getTime() + "\">");
 86  
 
 87  5
                         increaseIndentation();
 88  5
                         dumpSources();
 89  5
                         dumpPackages(projectData);
 90  5
                         decreaseIndentation();
 91  5
                         println("</coverage>");
 92  
                 }
 93  
                 finally
 94  
                 {
 95  5
                         pw.close();
 96  5
                 }
 97  5
         }
 98  
 
 99  
         void increaseIndentation()
 100  
         {
 101  174
                 indent++;
 102  174
         }
 103  
 
 104  
         void decreaseIndentation()
 105  
         {
 106  174
                 if (indent > 0)
 107  174
                         indent--;
 108  174
         }
 109  
 
 110  
         void indent()
 111  
         {
 112  3858
                 for (int i = 0; i < indent; i++)
 113  
                 {
 114  3290
                         pw.print("\t");
 115  
                 }
 116  568
         }
 117  
 
 118  
         void println(String ln)
 119  
         {
 120  568
                 indent();
 121  568
                 pw.println(ln);
 122  568
         }
 123  
 
 124  
         private void dumpSources()
 125  
         {
 126  5
                 println("<sources>");
 127  5
                 increaseIndentation();
 128  5
                 for (Iterator it = finder.getSourceDirectoryList().iterator(); it.hasNext(); ) {
 129  4
                         String dir = (String) it.next();
 130  4
                         dumpSource(dir);
 131  4
                 }
 132  5
                 decreaseIndentation();
 133  5
                 println("</sources>");
 134  5
         }
 135  
 
 136  
         private void dumpSource(String sourceDirectory)
 137  
         {
 138  4
                 println("<source>" + sourceDirectory + "</source>");
 139  4
         }
 140  
 
 141  
         private void dumpPackages(ProjectData projectData)
 142  
         {
 143  5
                 println("<packages>");
 144  5
                 increaseIndentation();
 145  
 
 146  5
                 Iterator it = projectData.getPackages().iterator();
 147  13
                 while (it.hasNext())
 148  
                 {
 149  8
                         dumpPackage((PackageData)it.next());
 150  8
                 }
 151  
 
 152  5
                 decreaseIndentation();
 153  5
                 println("</packages>");
 154  5
         }
 155  
 
 156  
         private void dumpPackage(PackageData packageData)
 157  
         {
 158  8
                 logger.debug("Dumping package " + packageData.getName());
 159  
 
 160  8
                 println("<package name=\"" + packageData.getName()
 161  
                                 + "\" line-rate=\"" + packageData.getLineCoverageRate()
 162  
                                 + "\" branch-rate=\"" + packageData.getBranchCoverageRate()
 163  
                                 + "\" complexity=\"" + complexity.getCCNForPackage(packageData) + "\"" + ">");
 164  8
                 increaseIndentation();
 165  8
                 dumpSourceFiles(packageData);
 166  8
                 decreaseIndentation();
 167  8
                 println("</package>");
 168  8
         }
 169  
 
 170  
         private void dumpSourceFiles(PackageData packageData)
 171  
         {
 172  8
                 println("<classes>");
 173  8
                 increaseIndentation();
 174  
 
 175  8
                 Iterator it = packageData.getSourceFiles().iterator();
 176  23
                 while (it.hasNext())
 177  
                 {
 178  15
                         dumpClasses((SourceFileData)it.next());
 179  15
                 }
 180  
 
 181  8
                 decreaseIndentation();
 182  8
                 println("</classes>");
 183  8
         }
 184  
 
 185  
         private void dumpClasses(SourceFileData sourceFileData)
 186  
         {
 187  15
                 Iterator it = sourceFileData.getClasses().iterator();
 188  30
                 while (it.hasNext())
 189  
                 {
 190  15
                         dumpClass((ClassData)it.next());
 191  15
                 }
 192  15
         }
 193  
 
 194  
         private void dumpClass(ClassData classData)
 195  
         {
 196  15
                 logger.debug("Dumping class " + classData.getName());
 197  
 
 198  15
                 println("<class name=\"" + classData.getName() + "\" filename=\""
 199  
                                 + classData.getSourceFileName() + "\" line-rate=\""
 200  
                                 + classData.getLineCoverageRate() + "\" branch-rate=\""
 201  
                                 + classData.getBranchCoverageRate() + "\" complexity=\""
 202  
                                 + complexity.getCCNForClass(classData) + "\"" + ">");
 203  15
                 increaseIndentation();
 204  
 
 205  15
                 dumpMethods(classData);
 206  15
                 dumpLines(classData);
 207  
 
 208  15
                 decreaseIndentation();
 209  15
                 println("</class>");
 210  15
         }
 211  
 
 212  
         private void dumpMethods(ClassData classData)
 213  
         {
 214  15
                 println("<methods>");
 215  15
                 increaseIndentation();
 216  
 
 217  15
                 SortedSet sortedMethods = new TreeSet();
 218  15
                 sortedMethods.addAll(classData.getMethodNamesAndDescriptors());
 219  15
                 Iterator iter = sortedMethods.iterator();
 220  50
                 while (iter.hasNext())
 221  
                 {
 222  35
                         dumpMethod(classData, (String)iter.next());
 223  35
                 }
 224  
 
 225  15
                 decreaseIndentation();
 226  15
                 println("</methods>");
 227  15
         }
 228  
 
 229  
         private void dumpMethod(ClassData classData, String nameAndSig)
 230  
         {
 231  35
                 String name = nameAndSig.substring(0, nameAndSig.indexOf('('));
 232  35
                 String signature = nameAndSig.substring(nameAndSig.indexOf('('));
 233  35
                 double lineRate = classData.getLineCoverageRate(nameAndSig);
 234  35
                 double branchRate = classData.getBranchCoverageRate(nameAndSig);
 235  
 
 236  35
                 println("<method name=\"" + xmlEscape(name) + "\" signature=\""
 237  
                                 + xmlEscape(signature) + "\" line-rate=\"" + lineRate
 238  
                                 + "\" branch-rate=\"" + branchRate + "\">");
 239  35
                 increaseIndentation();
 240  35
                 dumpLines(classData, nameAndSig);
 241  35
                 decreaseIndentation();
 242  35
                 println("</method>");
 243  35
         }
 244  
 
 245  
         private static String xmlEscape(String str)
 246  
         {
 247  70
                 str = StringUtil.replaceAll(str, "<", "&lt;");
 248  70
                 str = StringUtil.replaceAll(str, ">", "&gt;");
 249  70
                 return str;
 250  
         }
 251  
 
 252  
         private void dumpLines(ClassData classData)
 253  
         {
 254  15
                 dumpLines(classData.getLines());
 255  15
         }
 256  
 
 257  
         private void dumpLines(ClassData classData, String methodNameAndSig)
 258  
         {
 259  35
                 dumpLines(classData.getLines(methodNameAndSig));
 260  35
         }
 261  
 
 262  
         private void dumpLines(Collection lines)
 263  
         {
 264  50
                 println("<lines>");
 265  50
                 increaseIndentation();
 266  
 
 267  50
                 SortedSet sortedLines = new TreeSet();
 268  50
                 sortedLines.addAll(lines);
 269  50
                 Iterator iter = sortedLines.iterator();
 270  259
                 while (iter.hasNext())
 271  
                 {
 272  209
                         dumpLine((LineData)iter.next());
 273  209
                 }
 274  
 
 275  50
                 decreaseIndentation();
 276  50
                 println("</lines>");
 277  50
         }
 278  
 
 279  
         private void dumpLine(LineData lineData)
 280  
         {
 281  209
                 int lineNumber = lineData.getLineNumber();
 282  209
                 long hitCount = lineData.getHits();
 283  209
                 boolean hasBranch = lineData.hasBranch();
 284  209
                 String conditionCoverage = lineData.getConditionCoverage();
 285  
 
 286  209
                 String lineInfo = "<line number=\"" + lineNumber + "\" hits=\"" + hitCount
 287  
                                 + "\" branch=\"" + hasBranch + "\"";
 288  209
                 if (hasBranch)
 289  
                 {
 290  10
                         println(lineInfo + " condition-coverage=\"" + conditionCoverage + "\">");
 291  10
                         dumpConditions(lineData);
 292  10
                         println("</line>");
 293  10
                 } else
 294  
                 {
 295  199
                         println(lineInfo + "/>");
 296  
                 }
 297  209
         }
 298  
 
 299  
         private void dumpConditions(LineData lineData)
 300  
         {
 301  10
                 increaseIndentation();
 302  10
                 println("<conditions>");
 303  
 
 304  28
                 for (int i = 0; i < lineData.getConditionSize(); i++)
 305  
                 {
 306  18
                         Object conditionData = lineData.getConditionData(i);
 307  18
                         String coverage = lineData.getConditionCoverage(i);
 308  18
                         dumpCondition(conditionData, coverage);
 309  
                 }
 310  
 
 311  10
                 println("</conditions>");
 312  10
                 decreaseIndentation();
 313  10
         }
 314  
 
 315  
         private void dumpCondition(Object conditionData, String coverage)
 316  
         {
 317  18
                 increaseIndentation();
 318  18
                 StringBuffer buffer = new StringBuffer("<condition");
 319  18
                 if (conditionData instanceof JumpData)
 320  
                 {
 321  14
                         JumpData jumpData = (JumpData) conditionData;
 322  14
                         buffer.append(" number=\"").append(jumpData.getConditionNumber()).append("\"");
 323  14
                         buffer.append(" type=\"").append("jump").append("\"");
 324  14
                         buffer.append(" coverage=\"").append(coverage).append("\"");
 325  14
                 }
 326  
                 else
 327  
                 {
 328  4
                         SwitchData switchData = (SwitchData) conditionData;
 329  4
                         buffer.append(" number=\"").append(switchData.getSwitchNumber()).append("\"");
 330  4
                         buffer.append(" type=\"").append("switch").append("\"");
 331  4
                         buffer.append(" coverage=\"").append(coverage).append("\"");
 332  
                 }
 333  18
                 buffer.append("/>");
 334  18
                 println(buffer.toString());
 335  18
                 decreaseIndentation();
 336  18
         }
 337  
 
 338  
 }