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