HTMLFormatter.java
/*******************************************************************************
* Copyright (c) 2009, 2024 Mountainminds GmbH & Co. KG and Contributors
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
package org.jacoco.report.html;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import org.jacoco.core.analysis.IBundleCoverage;
import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
import org.jacoco.core.data.ExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.ILanguageNames;
import org.jacoco.report.IMultiReportOutput;
import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.IReportVisitor;
import org.jacoco.report.ISourceFileLocator;
import org.jacoco.report.JavaNames;
import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLGroupVisitor;
import org.jacoco.report.internal.html.IHTMLReportContext;
import org.jacoco.report.internal.html.ILinkable;
import org.jacoco.report.internal.html.index.ElementIndex;
import org.jacoco.report.internal.html.index.IIndexUpdate;
import org.jacoco.report.internal.html.page.BundlePage;
import org.jacoco.report.internal.html.page.ReportPage;
import org.jacoco.report.internal.html.page.SessionsPage;
import org.jacoco.report.internal.html.resources.Resources;
import org.jacoco.report.internal.html.resources.Styles;
import org.jacoco.report.internal.html.table.BarColumn;
import org.jacoco.report.internal.html.table.CounterColumn;
import org.jacoco.report.internal.html.table.LabelColumn;
import org.jacoco.report.internal.html.table.PercentageColumn;
import org.jacoco.report.internal.html.table.Table;
/**
* Formatter for coverage reports in multiple HTML pages.
*/
public class HTMLFormatter implements IHTMLReportContext {
private ILanguageNames languageNames = new JavaNames();
private Locale locale = Locale.getDefault();
private String footerText = "";
private String outputEncoding = "UTF-8";
private Resources resources;
private ElementIndex index;
private SessionsPage sessionsPage;
private Table table;
/**
* New instance with default settings.
*/
public HTMLFormatter() {
}
/**
* Sets the implementation for language name display. Java language names
* are defined by default.
*
* @param languageNames
* converter for language specific names
*/
public void setLanguageNames(final ILanguageNames languageNames) {
this.languageNames = languageNames;
}
/**
* Sets the locale used for report rendering. The current default locale is
* used by default.
*
* @param locale
* locale used for report rendering
*/
public void setLocale(final Locale locale) {
this.locale = locale;
}
/**
* Sets the optional text that should be included in every footer page.
*
* @param footerText
* footer text
*/
public void setFooterText(final String footerText) {
this.footerText = footerText;
}
/**
* Sets the encoding used for generated HTML pages. Default is UTF-8.
*
* @param outputEncoding
* HTML output encoding
*/
public void setOutputEncoding(final String outputEncoding) {
this.outputEncoding = outputEncoding;
}
// === IHTMLReportContext ===
public ILanguageNames getLanguageNames() {
return languageNames;
}
public Resources getResources() {
return resources;
}
public Table getTable() {
if (table == null) {
table = createTable();
}
return table;
}
private Table createTable() {
final Table t = new Table();
t.add("Element", null, new LabelColumn(), false);
t.add("Missed Instructions", Styles.BAR,
new BarColumn(CounterEntity.INSTRUCTION, locale), true);
t.add("Cov.", Styles.CTR2,
new PercentageColumn(CounterEntity.INSTRUCTION, locale), false);
t.add("Missed Branches", Styles.BAR,
new BarColumn(CounterEntity.BRANCH, locale), false);
t.add("Cov.", Styles.CTR2,
new PercentageColumn(CounterEntity.BRANCH, locale), false);
addMissedTotalColumns(t, "Cxty", CounterEntity.COMPLEXITY);
addMissedTotalColumns(t, "Lines", CounterEntity.LINE);
addMissedTotalColumns(t, "Methods", CounterEntity.METHOD);
addMissedTotalColumns(t, "Classes", CounterEntity.CLASS);
return t;
}
private void addMissedTotalColumns(final Table table, final String label,
final CounterEntity entity) {
table.add("Missed", Styles.CTR1,
CounterColumn.newMissed(entity, locale), false);
table.add(label, Styles.CTR2, CounterColumn.newTotal(entity, locale),
false);
}
public String getFooterText() {
return footerText;
}
public ILinkable getSessionsPage() {
return sessionsPage;
}
public String getOutputEncoding() {
return outputEncoding;
}
public IIndexUpdate getIndexUpdate() {
return index;
}
public Locale getLocale() {
return locale;
}
/**
* Creates a new visitor to write a report to the given output.
*
* @param output
* output to write the report to
* @return visitor to emit the report data to
* @throws IOException
* in case of problems with the output stream
*/
public IReportVisitor createVisitor(final IMultiReportOutput output)
throws IOException {
final ReportOutputFolder root = new ReportOutputFolder(output);
resources = new Resources(root);
resources.copyResources();
index = new ElementIndex(root);
return new IReportVisitor() {
private List<SessionInfo> sessionInfos;
private Collection<ExecutionData> executionData;
private HTMLGroupVisitor groupHandler;
public void visitInfo(final List<SessionInfo> sessionInfos,
final Collection<ExecutionData> executionData)
throws IOException {
this.sessionInfos = sessionInfos;
this.executionData = executionData;
}
public void visitBundle(final IBundleCoverage bundle,
final ISourceFileLocator locator) throws IOException {
final BundlePage page = new BundlePage(bundle, null, locator,
root, HTMLFormatter.this);
createSessionsPage(page);
page.render();
}
public IReportGroupVisitor visitGroup(final String name)
throws IOException {
groupHandler = new HTMLGroupVisitor(null, root,
HTMLFormatter.this, name);
createSessionsPage(groupHandler.getPage());
return groupHandler;
}
private void createSessionsPage(final ReportPage rootpage) {
sessionsPage = new SessionsPage(sessionInfos, executionData,
index, rootpage, root, HTMLFormatter.this);
}
public void visitEnd() throws IOException {
if (groupHandler != null) {
groupHandler.visitEnd();
}
sessionsPage.render();
output.close();
}
};
}
}