aboutsummaryrefslogtreecommitdiff
path: root/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java
blob: 65782d974323b8765b85a36b255d5ddb49af4bc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*******************************************************************************
 * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Marc R. Hoffmann - initial API and implementation
 *    
 *******************************************************************************/
package org.jacoco.report.internal.xml;

import java.io.IOException;
import java.io.OutputStream;

import org.jacoco.core.analysis.IClassCoverage;
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
import org.jacoco.core.analysis.ILine;
import org.jacoco.core.analysis.IMethodCoverage;
import org.jacoco.core.data.SessionInfo;

/**
 * A {@link XMLElement} with utility methods to create JaCoCo XML reports.
 */
public class ReportElement extends XMLElement {

	private static final String PUBID = "-//JACOCO//DTD Report 1.1//EN";

	private static final String SYSTEM = "report.dtd";

	/**
	 * Creates a <code>report</code> root element for a XML report.
	 * 
	 * @param name
	 *            value for the name attribute
	 * @param encoding
	 *            character encoding used for output
	 * @param output
	 *            output stream will be closed if the root element is closed
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public ReportElement(final String name, final OutputStream output,
			final String encoding) throws IOException {
		super("report", PUBID, SYSTEM, true, encoding, output);
		attr("name", name);
	}

	private ReportElement(final String name, final ReportElement parent)
			throws IOException {
		super(name, parent);
	}

	@Override
	public ReportElement element(final String name) throws IOException {
		return new ReportElement(name, this);
	}

	private ReportElement namedElement(final String elementName,
			final String name) throws IOException {
		final ReportElement element = element(elementName);
		element.attr("name", name);
		return element;
	}

	/**
	 * Creates a 'sessioninfo' element.
	 * 
	 * @param info
	 *            info object to write out
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public void sessioninfo(final SessionInfo info) throws IOException {
		final ReportElement sessioninfo = element("sessioninfo");
		sessioninfo.attr("id", info.getId());
		sessioninfo.attr("start", info.getStartTimeStamp());
		sessioninfo.attr("dump", info.getDumpTimeStamp());
	}

	/**
	 * Creates a 'group' element.
	 * 
	 * @param name
	 *            value for the name attribute
	 * @return 'group' element
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public ReportElement group(final String name) throws IOException {
		return namedElement("group", name);
	}

	/**
	 * Creates a 'package' element.
	 * 
	 * @param name
	 *            value for the name attribute
	 * @return 'package' element
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public ReportElement packageElement(final String name) throws IOException {
		return namedElement("package", name);
	}

	/**
	 * Creates a 'class' element.
	 * 
	 * @param coverage
	 *            class coverage node to write out
	 * @return 'class' element
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public ReportElement classElement(final IClassCoverage coverage)
			throws IOException {
		final ReportElement element = namedElement("class", coverage.getName());
		element.attr("sourcefilename", coverage.getSourceFileName());
		return element;
	}

	/**
	 * Creates a 'method' element.
	 * 
	 * @param coverage
	 *            method coverage node to write out
	 * @return 'method' element
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public ReportElement method(final IMethodCoverage coverage)
			throws IOException {
		final ReportElement element = namedElement("method",
				coverage.getName());
		element.attr("desc", coverage.getDesc());
		final int line = coverage.getFirstLine();
		if (line != -1) {
			element.attr("line", line);
		}
		return element;
	}

	/**
	 * Creates a 'sourcefile' element.
	 * 
	 * @param name
	 *            value for the name attribute
	 * @return 'sourcefile' element
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public ReportElement sourcefile(final String name) throws IOException {
		return namedElement("sourcefile", name);
	}

	/**
	 * Creates a 'line' element.
	 * 
	 * @param nr
	 *            line number
	 * @param line
	 *            line object to write out
	 * 
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public void line(final int nr, final ILine line) throws IOException {
		final ReportElement element = element("line");
		element.attr("nr", nr);
		counterAttributes(element, "mi", "ci", line.getInstructionCounter());
		counterAttributes(element, "mb", "cb", line.getBranchCounter());
	}

	/**
	 * Creates a 'counter' element.
	 * 
	 * @param counterEntity
	 *            entity of this counter
	 * 
	 * @param counter
	 *            counter object to write out
	 * 
	 * @throws IOException
	 *             in case of problems with the underlying output
	 */
	public void counter(final CounterEntity counterEntity,
			final ICounter counter) throws IOException {
		final ReportElement counterNode = element("counter");
		counterNode.attr("type", counterEntity.name());
		counterAttributes(counterNode, "missed", "covered", counter);
	}

	private static void counterAttributes(final XMLElement element,
			final String missedattr, final String coveredattr,
			final ICounter counter) throws IOException {
		element.attr(missedattr, counter.getMissedCount());
		element.attr(coveredattr, counter.getCoveredCount());
	}

}