XMLCoverageWriter.java revision 57f7cf06888f1e34f9ab2e3129c3d433826ecbe1
1/******************************************************************************* 2 * Copyright (c) 2009, 2013 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 * if XML can't be written to the underlying output 44 * 45 */ 46 public static XMLElement createChild(final XMLElement parent, 47 final String tagname, final String name) throws IOException { 48 final XMLElement child = parent.element(tagname); 49 child.attr("name", name); 50 return child; 51 } 52 53 /** 54 * Writes the structure of a given bundle. 55 * 56 * @param bundle 57 * bundle coverage data 58 * @param element 59 * container element for the bundle data 60 * @throws IOException 61 * if XML can't be written to the underlying output 62 */ 63 public static void writeBundle(final IBundleCoverage bundle, 64 final XMLElement element) throws IOException { 65 for (final IPackageCoverage p : bundle.getPackages()) { 66 writePackage(p, element); 67 } 68 writeCounters(bundle, element); 69 } 70 71 private static void writePackage(final IPackageCoverage p, 72 final XMLElement parent) throws IOException { 73 final XMLElement element = createChild(parent, "package", p.getName()); 74 for (final IClassCoverage c : p.getClasses()) { 75 writeClass(c, element); 76 } 77 for (final ISourceFileCoverage s : p.getSourceFiles()) { 78 writeSourceFile(s, element); 79 } 80 writeCounters(p, element); 81 } 82 83 private static void writeClass(final IClassCoverage c, 84 final XMLElement parent) throws IOException { 85 final XMLElement element = createChild(parent, "class", c.getName()); 86 for (final IMethodCoverage m : c.getMethods()) { 87 writeMethod(m, element); 88 } 89 writeCounters(c, element); 90 } 91 92 private static void writeMethod(final IMethodCoverage m, 93 final XMLElement parent) throws IOException { 94 final XMLElement element = createChild(parent, "method", m.getName()); 95 element.attr("desc", m.getDesc()); 96 final int line = m.getFirstLine(); 97 if (line != -1) { 98 element.attr("line", line); 99 } 100 writeCounters(m, element); 101 } 102 103 private static void writeSourceFile(final ISourceFileCoverage s, 104 final XMLElement parent) throws IOException { 105 final XMLElement element = createChild(parent, "sourcefile", 106 s.getName()); 107 writeLines(s, element); 108 writeCounters(s, element); 109 } 110 111 /** 112 * Writes all non-zero counters of the given node. 113 * 114 * @param node 115 * node to retrieve counters from 116 * @param parent 117 * container for the counter elements 118 * @throws IOException 119 * if XML can't be written to the underlying output 120 */ 121 public static void writeCounters(final ICoverageNode node, 122 final XMLElement parent) throws IOException { 123 for (final CounterEntity counterEntity : CounterEntity.values()) { 124 final ICounter counter = node.getCounter(counterEntity); 125 if (counter.getTotalCount() > 0) { 126 final XMLElement counterNode = parent.element("counter"); 127 counterNode.attr("type", counterEntity.name()); 128 writeCounter(counterNode, "missed", "covered", counter); 129 counterNode.close(); 130 } 131 } 132 } 133 134 private static void writeLines(final ISourceNode source, 135 final XMLElement parent) throws IOException { 136 final int last = source.getLastLine(); 137 for (int nr = source.getFirstLine(); nr <= last; nr++) { 138 final ILine line = source.getLine(nr); 139 if (line.getStatus() != ICounter.EMPTY) { 140 final XMLElement element = parent.element("line"); 141 element.attr("nr", nr); 142 writeCounter(element, "mi", "ci", line.getInstructionCounter()); 143 writeCounter(element, "mb", "cb", line.getBranchCounter()); 144 } 145 } 146 } 147 148 private static void writeCounter(final XMLElement element, 149 final String missedattr, final String coveredattr, 150 final ICounter counter) throws IOException { 151 element.attr(missedattr, counter.getMissedCount()); 152 element.attr(coveredattr, counter.getCoveredCount()); 153 } 154 155 private XMLCoverageWriter() { 156 } 157 158} 159