• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2009, 2018 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  *******************************************************************************/
12 package org.jacoco.report.internal.xml;
13 
14 import java.io.IOException;
15 
16 import org.jacoco.core.analysis.IBundleCoverage;
17 import org.jacoco.core.analysis.IClassCoverage;
18 import org.jacoco.core.analysis.ICounter;
19 import org.jacoco.core.analysis.ICoverageNode;
20 import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
21 import org.jacoco.core.analysis.ILine;
22 import org.jacoco.core.analysis.IMethodCoverage;
23 import org.jacoco.core.analysis.IPackageCoverage;
24 import org.jacoco.core.analysis.ISourceFileCoverage;
25 import org.jacoco.core.analysis.ISourceNode;
26 
27 /**
28  * Serializes coverage data as XML fragments.
29  */
30 public 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 	 */
createChild(final XMLElement parent, final String tagname, final String name)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 	 */
writeBundle(final IBundleCoverage bundle, final XMLElement element)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 
writePackage(final IPackageCoverage p, final XMLElement parent)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 
writeClass(final IClassCoverage c, final XMLElement parent)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 
writeMethod(final IMethodCoverage m, final XMLElement parent)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 
writeSourceFile(final ISourceFileCoverage s, final XMLElement parent)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 	 */
writeCounters(final ICoverageNode node, final XMLElement parent)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 
writeLines(final ISourceNode source, final XMLElement parent)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 
writeCounter(final XMLElement element, final String missedattr, final String coveredattr, final ICounter counter)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 
XMLCoverageWriter()155 	private XMLCoverageWriter() {
156 	}
157 
158 }
159