HTMLFormatter.java revision 0e99a259a4c85819cec139e8f32b9537be716521
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.html;
13
14import static org.jacoco.core.analysis.ICoverageNode.CounterEntity.BRANCH;
15import static org.jacoco.core.analysis.ICoverageNode.CounterEntity.CLASS;
16import static org.jacoco.core.analysis.ICoverageNode.CounterEntity.INSTRUCTION;
17import static org.jacoco.core.analysis.ICoverageNode.CounterEntity.LINE;
18import static org.jacoco.core.analysis.ICoverageNode.CounterEntity.METHOD;
19
20import java.io.IOException;
21import java.util.Collection;
22import java.util.List;
23import java.util.Locale;
24
25import org.jacoco.core.analysis.IBundleCoverage;
26import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
27import org.jacoco.core.data.ExecutionData;
28import org.jacoco.core.data.SessionInfo;
29import org.jacoco.report.ILanguageNames;
30import org.jacoco.report.IMultiReportOutput;
31import org.jacoco.report.IReportGroupVisitor;
32import org.jacoco.report.IReportVisitor;
33import org.jacoco.report.ISourceFileLocator;
34import org.jacoco.report.JavaNames;
35import org.jacoco.report.internal.ReportOutputFolder;
36import org.jacoco.report.internal.html.HTMLGroupVisitor;
37import org.jacoco.report.internal.html.IHTMLReportContext;
38import org.jacoco.report.internal.html.ILinkable;
39import org.jacoco.report.internal.html.index.ElementIndex;
40import org.jacoco.report.internal.html.index.IIndexUpdate;
41import org.jacoco.report.internal.html.page.BundlePage;
42import org.jacoco.report.internal.html.page.ReportPage;
43import org.jacoco.report.internal.html.page.SessionsPage;
44import org.jacoco.report.internal.html.resources.Resources;
45import org.jacoco.report.internal.html.resources.Styles;
46import org.jacoco.report.internal.html.table.BarColumn;
47import org.jacoco.report.internal.html.table.CounterColumn;
48import org.jacoco.report.internal.html.table.LabelColumn;
49import org.jacoco.report.internal.html.table.PercentageColumn;
50import org.jacoco.report.internal.html.table.Table;
51
52/**
53 * Formatter for coverage reports in multiple HTML pages.
54 */
55public class HTMLFormatter implements IHTMLReportContext {
56
57	private ILanguageNames languageNames = new JavaNames();
58
59	private Locale locale = Locale.getDefault();
60
61	private String footerText = "";
62
63	private String outputEncoding = "UTF-8";
64
65	private int tabWidth = 4;
66
67	private Resources resources;
68
69	private ElementIndex index;
70
71	private SessionsPage sessionsPage;
72
73	private Table table;
74
75	/**
76	 * New instance with default settings.
77	 */
78	public HTMLFormatter() {
79	}
80
81	/**
82	 * Sets the implementation for language name display. Java language names
83	 * are defined by default.
84	 *
85	 * @param languageNames
86	 *            converter for language specific names
87	 */
88	public void setLanguageNames(final ILanguageNames languageNames) {
89		this.languageNames = languageNames;
90	}
91
92	/**
93	 * Sets the locale used for report rendering. The current default locale is
94	 * used by default.
95	 *
96	 * @param locale
97	 *            locale used for report rendering
98	 */
99	public void setLocale(final Locale locale) {
100		this.locale = locale;
101	}
102
103	/**
104	 * Sets the optional text that should be included in every footer page.
105	 *
106	 * @param footerText
107	 *            footer text
108	 */
109	public void setFooterText(final String footerText) {
110		this.footerText = footerText;
111	}
112
113	/**
114	 * Sets the encoding used for generated HTML pages. Default is UTF-8.
115	 *
116	 * @param outputEncoding
117	 *            HTML output encoding
118	 */
119	public void setOutputEncoding(final String outputEncoding) {
120		this.outputEncoding = outputEncoding;
121	}
122
123	/**
124	 * Sets the number of blank characters that represent a tab in source code.
125	 *
126	 * @param tabWidth
127	 *            tab width as number of blanks
128	 */
129	public void setTabWidth(final int tabWidth) {
130		this.tabWidth = tabWidth;
131	}
132
133	// === IHTMLReportContext ===
134
135	public ILanguageNames getLanguageNames() {
136		return languageNames;
137	}
138
139	public Resources getResources() {
140		return resources;
141	}
142
143	public Table getTable() {
144		if (table == null) {
145			table = createTable();
146		}
147		return table;
148	}
149
150	private Table createTable() {
151		final Table table = new Table();
152		table.add("Element", null, new LabelColumn(), false);
153		table.add("Missed Instructions", Styles.BAR, new BarColumn(INSTRUCTION,
154				locale), true);
155		table.add("Cov.", Styles.CTR2,
156				new PercentageColumn(INSTRUCTION, locale), false);
157		table.add("Missed Branches", Styles.BAR, new BarColumn(BRANCH, locale),
158				false);
159		table.add("Cov.", Styles.CTR2, new PercentageColumn(BRANCH, locale),
160				false);
161		addMissedTotalColumns(table, "Lines", LINE);
162		addMissedTotalColumns(table, "Methods", METHOD);
163		addMissedTotalColumns(table, "Classes", CLASS);
164		return table;
165	}
166
167	private void addMissedTotalColumns(final Table table, final String label,
168			final CounterEntity entity) {
169		table.add("Missed", Styles.CTR1,
170				CounterColumn.newMissed(entity, locale), false);
171		table.add(label, Styles.CTR2, CounterColumn.newTotal(entity, locale),
172				false);
173	}
174
175	public String getFooterText() {
176		return footerText;
177	}
178
179	public ILinkable getSessionsPage() {
180		return sessionsPage;
181	}
182
183	public String getOutputEncoding() {
184		return outputEncoding;
185	}
186
187	public int getTabWidth() {
188		return tabWidth;
189	}
190
191	public IIndexUpdate getIndexUpdate() {
192		return index;
193	}
194
195	public Locale getLocale() {
196		return locale;
197	}
198
199	/**
200	 * Creates a new visitor to write a report to the given output.
201	 *
202	 * @param output
203	 *            output to write the report to
204	 * @return visitor to emit the report data to
205	 * @throws IOException
206	 *             in case of problems with the output stream
207	 */
208	public IReportVisitor createVisitor(final IMultiReportOutput output)
209			throws IOException {
210		final ReportOutputFolder root = new ReportOutputFolder(output);
211		resources = new Resources(root);
212		resources.copyResources();
213		index = new ElementIndex(root);
214		return new IReportVisitor() {
215
216			private List<SessionInfo> sessionInfos;
217			private Collection<ExecutionData> executionData;
218
219			private HTMLGroupVisitor groupHandler;
220
221			public void visitInfo(final List<SessionInfo> sessionInfos,
222					final Collection<ExecutionData> executionData)
223					throws IOException {
224				this.sessionInfos = sessionInfos;
225				this.executionData = executionData;
226			}
227
228			public void visitBundle(final IBundleCoverage bundle,
229					final ISourceFileLocator locator) throws IOException {
230				final BundlePage page = new BundlePage(bundle, null, locator,
231						root, HTMLFormatter.this);
232				createSessionsPage(page);
233				page.render();
234			}
235
236			public IReportGroupVisitor visitGroup(final String name)
237					throws IOException {
238				groupHandler = new HTMLGroupVisitor(null, root,
239						HTMLFormatter.this, name);
240				createSessionsPage(groupHandler.getPage());
241				return groupHandler;
242
243			}
244
245			private void createSessionsPage(final ReportPage rootpage) {
246				sessionsPage = new SessionsPage(sessionInfos, executionData,
247						index, rootpage, root, HTMLFormatter.this);
248			}
249
250			public void visitEnd() throws IOException {
251				if (groupHandler != null) {
252					groupHandler.visitEnd();
253				}
254				sessionsPage.render();
255				output.close();
256			}
257		};
258	}
259}
260