Skip to content

Instantly share code, notes, and snippets.

@akisaarinen
Created August 20, 2012 09:42
Show Gist options
  • Save akisaarinen/3402702 to your computer and use it in GitHub Desktop.
Save akisaarinen/3402702 to your computer and use it in GitHub Desktop.
XMLReport.java
/*
* Cobertura - http://cobertura.sourceforge.net/
*
* Copyright (C) 2003 jcoverage ltd.
* Copyright (C) 2005 Mark Doliner
* Copyright (C) 2005 Jeremy Thomerson
* Copyright (C) 2006 Jiri Mares
* Copyright (C) 2008 Julian Gamble
*
* Cobertura is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* Cobertura 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cobertura; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
package net.sourceforge.cobertura.reporting.xml;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import net.sourceforge.cobertura.coveragedata.ClassData;
import net.sourceforge.cobertura.coveragedata.JumpData;
import net.sourceforge.cobertura.coveragedata.LineData;
import net.sourceforge.cobertura.coveragedata.PackageData;
import net.sourceforge.cobertura.coveragedata.ProjectData;
import net.sourceforge.cobertura.coveragedata.SourceFileData;
import net.sourceforge.cobertura.coveragedata.SwitchData;
import net.sourceforge.cobertura.reporting.ComplexityCalculator;
import net.sourceforge.cobertura.util.FileFinder;
import net.sourceforge.cobertura.util.Header;
import net.sourceforge.cobertura.util.IOUtil;
import net.sourceforge.cobertura.util.StringUtil;
import org.apache.log4j.Logger;
public class XMLReport
{
private static final Logger logger = Logger.getLogger(XMLReport.class);
protected final static String coverageDTD = "coverage-04.dtd";
private final PrintWriter pw;
private final FileFinder finder;
private final ComplexityCalculator complexity;
private int indent = 0;
public XMLReport(ProjectData projectData, File destinationDir,
FileFinder finder, ComplexityCalculator complexity) throws IOException
{
this.complexity = complexity;
this.finder = finder;
File file = new File(destinationDir, "coverage.xml");
pw = IOUtil.getPrintWriter(file);
try
{
println("<?xml version=\"1.0\"?>");
println("<!DOCTYPE coverage SYSTEM \"http://cobertura.sourceforge.net/xml/"
+ coverageDTD + "\">");
println("");
double ccn = complexity.getCCNForProject(projectData);
int numLinesCovered = projectData.getNumberOfCoveredLines();
int numLinesValid = projectData.getNumberOfValidLines();
int numBranchesCovered = projectData.getNumberOfCoveredBranches();
int numBranchesValid = projectData.getNumberOfValidBranches();
// TODO: Set a schema?
//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\">");
println(
"<coverage line-rate=\"" + projectData.getLineCoverageRate()
+ "\" branch-rate=\"" + projectData.getBranchCoverageRate()
+ "\" lines-covered=\"" + numLinesCovered
+ "\" lines-valid=\"" + numLinesValid
+ "\" branches-covered=\"" + numBranchesCovered
+ "\" branches-valid=\"" + numBranchesValid
+ "\" complexity=\"" + ccn
+ "\" version=\"" + Header.version()
+ "\" timestamp=\"" + new Date().getTime()
+ "\">");
increaseIndentation();
dumpSources();
dumpPackages(projectData);
decreaseIndentation();
println("</coverage>");
}
finally
{
pw.close();
}
}
void increaseIndentation()
{
indent++;
}
void decreaseIndentation()
{
if (indent > 0)
indent--;
}
void indent()
{
for (int i = 0; i < indent; i++)
{
pw.print("\t");
}
}
void println(String ln)
{
indent();
pw.println(ln);
}
private void dumpSources()
{
println("<sources>");
increaseIndentation();
for (Iterator it = finder.getSourceDirectoryList().iterator(); it.hasNext(); ) {
String dir = (String) it.next();
dumpSource(dir);
}
decreaseIndentation();
println("</sources>");
}
private void dumpSource(String sourceDirectory)
{
println("<source>" + sourceDirectory + "</source>");
}
private void dumpPackages(ProjectData projectData)
{
println("<packages>");
increaseIndentation();
Iterator it = projectData.getPackages().iterator();
while (it.hasNext())
{
dumpPackage((PackageData)it.next());
}
decreaseIndentation();
println("</packages>");
}
private void dumpPackage(PackageData packageData)
{
logger.debug("Dumping package " + packageData.getName());
println("<package name=\"" + packageData.getName()
+ "\" line-rate=\"" + packageData.getLineCoverageRate()
+ "\" branch-rate=\"" + packageData.getBranchCoverageRate()
+ "\" complexity=\"" + complexity.getCCNForPackage(packageData) + "\"" + ">");
increaseIndentation();
dumpSourceFiles(packageData);
decreaseIndentation();
println("</package>");
}
private void dumpSourceFiles(PackageData packageData)
{
println("<classes>");
increaseIndentation();
Iterator it = packageData.getSourceFiles().iterator();
while (it.hasNext())
{
dumpClasses((SourceFileData)it.next());
}
decreaseIndentation();
println("</classes>");
}
private void dumpClasses(SourceFileData sourceFileData)
{
Iterator it = sourceFileData.getClasses().iterator();
while (it.hasNext())
{
dumpClass((ClassData)it.next());
}
}
private void dumpClass(ClassData classData)
{
logger.debug("Dumping class " + classData.getName());
println("<class name=\"" + classData.getName() + "\" filename=\""
+ classData.getSourceFileName() + "\" line-rate=\""
+ classData.getLineCoverageRate() + "\" branch-rate=\""
+ classData.getBranchCoverageRate() + "\" complexity=\""
+ complexity.getCCNForClass(classData) + "\"" + ">");
increaseIndentation();
dumpMethods(classData);
dumpLines(classData);
decreaseIndentation();
println("</class>");
}
private void dumpMethods(ClassData classData)
{
println("<methods>");
increaseIndentation();
SortedSet sortedMethods = new TreeSet();
sortedMethods.addAll(classData.getMethodNamesAndDescriptors());
Iterator iter = sortedMethods.iterator();
while (iter.hasNext())
{
dumpMethod(classData, (String)iter.next());
}
decreaseIndentation();
println("</methods>");
}
private void dumpMethod(ClassData classData, String nameAndSig)
{
String name = nameAndSig.substring(0, nameAndSig.indexOf('('));
String signature = nameAndSig.substring(nameAndSig.indexOf('('));
double lineRate = classData.getLineCoverageRate(nameAndSig);
double branchRate = classData.getBranchCoverageRate(nameAndSig);
println("<method name=\"" + xmlEscape(name) + "\" signature=\""
+ xmlEscape(signature) + "\" line-rate=\"" + lineRate
+ "\" branch-rate=\"" + branchRate + "\">");
increaseIndentation();
dumpLines(classData, nameAndSig);
decreaseIndentation();
println("</method>");
}
private static String xmlEscape(String str)
{
str = StringUtil.replaceAll(str, "<", "&lt;");
str = StringUtil.replaceAll(str, ">", "&gt;");
return str;
}
private void dumpLines(ClassData classData)
{
dumpLines(classData.getLines());
}
private void dumpLines(ClassData classData, String methodNameAndSig)
{
dumpLines(classData.getLines(methodNameAndSig));
}
private void dumpLines(Collection lines)
{
println("<lines>");
increaseIndentation();
SortedSet sortedLines = new TreeSet();
sortedLines.addAll(lines);
Iterator iter = sortedLines.iterator();
while (iter.hasNext())
{
dumpLine((LineData)iter.next());
}
decreaseIndentation();
println("</lines>");
}
private void dumpLine(LineData lineData)
{
int lineNumber = lineData.getLineNumber();
long hitCount = lineData.getHits();
boolean hasBranch = lineData.hasBranch();
String conditionCoverage = lineData.getConditionCoverage();
String lineInfo = "<line number=\"" + lineNumber + "\" hits=\"" + hitCount
+ "\" branch=\"" + hasBranch + "\"";
if (hasBranch)
{
println(lineInfo + " condition-coverage=\"" + conditionCoverage + "\">");
dumpConditions(lineData);
println("</line>");
} else
{
println(lineInfo + "/>");
}
}
private void dumpConditions(LineData lineData)
{
increaseIndentation();
println("<conditions>");
for (int i = 0; i < lineData.getConditionSize(); i++)
{
Object conditionData = lineData.getConditionData(i);
String coverage = lineData.getConditionCoverage(i);
dumpCondition(conditionData, coverage);
}
println("</conditions>");
decreaseIndentation();
}
private void dumpCondition(Object conditionData, String coverage)
{
increaseIndentation();
StringBuffer buffer = new StringBuffer("<condition");
if (conditionData instanceof JumpData)
{
JumpData jumpData = (JumpData) conditionData;
buffer.append(" number=\"").append(jumpData.getConditionNumber()).append("\"");
buffer.append(" type=\"").append("jump").append("\"");
buffer.append(" coverage=\"").append(coverage).append("\"");
}
else
{
SwitchData switchData = (SwitchData) conditionData;
buffer.append(" number=\"").append(switchData.getSwitchNumber()).append("\"");
buffer.append(" type=\"").append("switch").append("\"");
buffer.append(" coverage=\"").append(coverage).append("\"");
}
buffer.append("/>");
println(buffer.toString());
decreaseIndentation();
}
}
@raimohanska
Copy link

You should replace tabs with spaces on line 326.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment