XMLCoverageWriter.java revision f01973aac61bab6ff3515c8855876bf6e162b180
1/******************************************************************************* 2 * Copyright (c) 2009, 2011 Mountainminds GmbH & Co. KG and Contributors 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * Marc R. Hoffmann - initial API and implementation 10 * 11 *******************************************************************************/ 12package org.jacoco.report.internal.xml; 13 14import java.io.IOException; 15 16import org.jacoco.core.analysis.IBundleCoverage; 17import org.jacoco.core.analysis.IClassCoverage; 18import org.jacoco.core.analysis.ICounter; 19import org.jacoco.core.analysis.ICoverageNode; 20import org.jacoco.core.analysis.ICoverageNode.CounterEntity; 21import org.jacoco.core.analysis.ILine; 22import org.jacoco.core.analysis.IMethodCoverage; 23import org.jacoco.core.analysis.IPackageCoverage; 24import org.jacoco.core.analysis.ISourceFileCoverage; 25import org.jacoco.core.analysis.ISourceNode; 26 27/** 28 * Serializes coverage data as XML fragments. 29 */ 30public final class XMLCoverageWriter { 31 32 /** 33 * Creates a child element with a name attribute. 34 * 35 * @param parent 36 * parent element 37 * @param tagname 38 * name of the child tag 39 * @param name 40 * value of the name attribute 41 * @return child element 42 * @throws IOException 43 */ 44 public static XMLElement createChild(final XMLElement parent, 45 final String tagname, final String name) throws IOException { 46 final XMLElement child = parent.element(tagname); 47 child.attr("name", name); 48 return child; 49 } 50 51 /** 52 * Writes the structure of a given bundle. 53 * 54 * @param bundle 55 * bundle coverage data 56 * @param element 57 * container element for the bundle data 58 * @throws IOException 59 */ 60 public static void writeBundle(final IBundleCoverage bundle, 61 final XMLElement element) throws IOException { 62 for (final IPackageCoverage p : bundle.getPackages()) { 63 writePackage(p, element); 64 } 65 writeCounters(bundle, element); 66 } 67 68 private static void writePackage(final IPackageCoverage p, 69 final XMLElement parent) throws IOException { 70 final XMLElement element = createChild(parent, "package", p.getName()); 71 for (final IClassCoverage c : p.getClasses()) { 72 writeClass(c, element); 73 } 74 for (final ISourceFileCoverage s : p.getSourceFiles()) { 75 writeSourceFile(s, element); 76 } 77 writeCounters(p, element); 78 } 79 80 private static void writeClass(final IClassCoverage c, 81 final XMLElement parent) throws IOException { 82 final XMLElement element = createChild(parent, "class", c.getName()); 83 for (final IMethodCoverage m : c.getMethods()) { 84 writeMethod(m, element); 85 } 86 writeCounters(c, element); 87 } 88 89 private static void writeMethod(final IMethodCoverage m, 90 final XMLElement parent) throws IOException { 91 final XMLElement element = createChild(parent, "method", m.getName()); 92 element.attr("desc", m.getDesc()); 93 final int line = m.getFirstLine(); 94 if (line != -1) { 95 element.attr("line", line); 96 } 97 writeCounters(m, element); 98 } 99 100 private static void writeSourceFile(final ISourceFileCoverage s, 101 final XMLElement parent) throws IOException { 102 final XMLElement element = createChild(parent, "sourcefile", 103 s.getName()); 104 writeLines(s, element); 105 writeCounters(s, element); 106 } 107 108 /** 109 * Writes all non-zero counters of the given node. 110 * 111 * @param node 112 * node to retrieve counters from 113 * @param parent 114 * container for the counter elements 115 * @throws IOException 116 */ 117 public static void writeCounters(final ICoverageNode node, 118 final XMLElement parent) throws IOException { 119 for (final CounterEntity counterEntity : CounterEntity.values()) { 120 final ICounter counter = node.getCounter(counterEntity); 121 if (counter.getTotalCount() > 0) { 122 final XMLElement counterNode = parent.element("counter"); 123 counterNode.attr("type", counterEntity.name()); 124 writeCounter(counterNode, "missed", "covered", counter); 125 counterNode.close(); 126 } 127 } 128 } 129 130 private static void writeLines(final ISourceNode source, 131 final XMLElement parent) throws IOException { 132 final int last = source.getLastLine(); 133 for (int nr = source.getFirstLine(); nr <= last; nr++) { 134 final ILine line = source.getLine(nr); 135 if (line.getStatus() != ICounter.EMPTY) { 136 final XMLElement element = parent.element("line"); 137 element.attr("nr", nr); 138 writeCounter(element, "mi", "ci", line.getInstructionCounter()); 139 writeCounter(element, "mb", "cb", line.getBranchCounter()); 140 } 141 } 142 } 143 144 private static void writeCounter(final XMLElement element, 145 final String missedattr, final String coveredattr, 146 final ICounter counter) throws IOException { 147 element.attr(missedattr, counter.getMissedCount()); 148 element.attr(coveredattr, counter.getCoveredCount()); 149 } 150 151 private XMLCoverageWriter() { 152 } 153 154} 155