Trac #53: Simplified reporting API, step 1.
diff --git a/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java b/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java
index 46f2eb5..511f853 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java
@@ -21,13 +21,11 @@
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.zip.ZipOutputStream;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
@@ -38,22 +36,17 @@
import org.apache.tools.ant.util.FileUtils;
import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder;
-import org.jacoco.core.analysis.CoverageNodeImpl;
import org.jacoco.core.analysis.IBundleCoverage;
-import org.jacoco.core.analysis.IClassCoverage;
import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.core.analysis.IPackageCoverage;
import org.jacoco.core.data.ExecutionDataReader;
import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.data.SessionInfoStore;
import org.jacoco.report.FileMultiReportOutput;
-import org.jacoco.report.FileSingleReportOutput;
import org.jacoco.report.IMultiReportOutput;
-import org.jacoco.report.IReportFormatter;
+import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.IReportVisitor;
import org.jacoco.report.ISourceFileLocator;
-import org.jacoco.report.MultiFormatter;
+import org.jacoco.report.MultiReportVisitor;
import org.jacoco.report.ZipMultiReportOutput;
import org.jacoco.report.csv.CSVFormatter;
import org.jacoco.report.html.HTMLFormatter;
@@ -145,9 +138,7 @@
*/
private interface IFormatterElement {
- IReportFormatter createFormatter() throws IOException;
-
- void finish() throws IOException;
+ IReportVisitor createVisitor() throws IOException;
}
@@ -166,8 +157,6 @@
private Locale locale = Locale.getDefault();
- private ZipOutputStream zipOutput;
-
/**
* Sets the output directory for the report.
*
@@ -220,15 +209,15 @@
this.locale = locale;
}
- public IReportFormatter createFormatter() throws IOException {
+ public IReportVisitor createVisitor() throws IOException {
final IMultiReportOutput output;
if (destfile != null) {
if (destdir != null) {
throw new BuildException(
"Either destination directory or file must be supplied, not both");
}
- zipOutput = new ZipOutputStream(new FileOutputStream(destfile));
- output = new ZipMultiReportOutput(zipOutput);
+ final FileOutputStream stream = new FileOutputStream(destfile);
+ output = new ZipMultiReportOutput(stream);
} else {
if (destdir == null) {
@@ -238,17 +227,10 @@
output = new FileMultiReportOutput(destdir);
}
final HTMLFormatter formatter = new HTMLFormatter();
- formatter.setReportOutput(output);
formatter.setFooterText(footer);
formatter.setOutputEncoding(encoding);
formatter.setLocale(locale);
- return formatter;
- }
-
- public void finish() throws IOException {
- if (zipOutput != null) {
- zipOutput.close();
- }
+ return formatter.createVisitor(output);
}
}
@@ -272,15 +254,14 @@
this.destfile = destfile;
}
- public IReportFormatter createFormatter() {
+ public IReportVisitor createVisitor() throws IOException {
if (destfile == null) {
throw new BuildException(
"Destination file must be supplied for csv report");
}
final CSVFormatter formatter = new CSVFormatter();
- formatter.setReportOutput(new FileSingleReportOutput(destfile));
formatter.setOutputEncoding(encoding);
- return formatter;
+ return formatter.createVisitor(new FileOutputStream(destfile));
}
/**
@@ -293,9 +274,6 @@
this.encoding = encoding;
}
- public void finish() {
- }
-
}
/**
@@ -327,18 +305,14 @@
this.encoding = encoding;
}
- public IReportFormatter createFormatter() {
+ public IReportVisitor createVisitor() throws IOException {
if (destfile == null) {
throw new BuildException(
"Destination file must be supplied for xml report");
}
final XMLFormatter formatter = new XMLFormatter();
- formatter.setReportOutput(new FileSingleReportOutput(destfile));
formatter.setOutputEncoding(encoding);
- return formatter;
- }
-
- public void finish() {
+ return formatter.createVisitor(new FileOutputStream(destfile));
}
}
@@ -408,9 +382,11 @@
public void execute() throws BuildException {
loadExecutionData();
try {
- final IReportFormatter formatter = createFormatter();
- createReport(formatter);
- finishFormatters();
+ final IReportVisitor visitor = createVisitor();
+ visitor.visitInfo(sessionInfoStore.getInfos(),
+ executionDataStore.getContents());
+ createReport(visitor, structure);
+ visitor.visitEnd();
} catch (final IOException e) {
throw new BuildException("Error while creating report.", e);
}
@@ -437,76 +413,59 @@
}
}
- private IReportFormatter createFormatter() throws IOException {
- final MultiFormatter multi = new MultiFormatter();
+ private IReportVisitor createVisitor() throws IOException {
+ final List<IReportVisitor> visitors = new ArrayList<IReportVisitor>();
for (final IFormatterElement f : formatters) {
- multi.add(f.createFormatter());
+ visitors.add(f.createVisitor());
}
- return multi;
+ return new MultiReportVisitor(visitors);
}
- private void finishFormatters() throws IOException {
- for (final IFormatterElement f : formatters) {
- f.finish();
- }
- }
-
- private void createReport(final IReportFormatter formatter)
- throws IOException {
- final CoverageNodeImpl node = createNode(structure);
- final IReportVisitor visitor = formatter.createReportVisitor(node,
- sessionInfoStore.getInfos(), executionDataStore.getContents());
- final SourceFileCollection sourceFileLocator = new SourceFileCollection(
- structure.sourcefiles);
- if (node.getElementType() == ElementType.BUNDLE) {
- visitBundle(visitor, (IBundleCoverage) node, sourceFileLocator);
- } else {
- for (final GroupElement g : structure.children) {
- createReport(g, visitor, node);
- }
- }
- visitor.visitEnd(sourceFileLocator);
- }
-
- private void createReport(final GroupElement group,
- final IReportVisitor parentVisitor,
- final CoverageNodeImpl parentNode) throws IOException {
- final CoverageNodeImpl node = createNode(group);
- final IReportVisitor visitor = parentVisitor.visitChild(node);
- final SourceFileCollection sourceFileLocator = new SourceFileCollection(
- group.sourcefiles);
- if (node.getElementType() == ElementType.BUNDLE) {
- visitBundle(visitor, (IBundleCoverage) node, sourceFileLocator);
- } else {
- for (final GroupElement g : group.children) {
- createReport(g, visitor, node);
- }
- }
- parentNode.increment(node);
- visitor.visitEnd(sourceFileLocator);
- }
-
- private CoverageNodeImpl createNode(final GroupElement group)
- throws IOException {
+ private void createReport(final IReportGroupVisitor visitor,
+ final GroupElement group) throws IOException {
if (group.name == null) {
throw new BuildException("Group name must be supplied");
}
if (group.children.size() > 0) {
- return new CoverageNodeImpl(ElementType.GROUP, group.name);
- } else {
- final CoverageBuilder builder = new CoverageBuilder();
- final Analyzer analyzer = new Analyzer(executionDataStore, builder);
- for (final Iterator<?> i = group.classfiles.iterator(); i.hasNext();) {
- final Resource resource = (Resource) i.next();
- if (resource.isDirectory() && resource instanceof FileResource) {
- analyzer.analyzeAll(((FileResource) resource).getFile());
- } else {
- final InputStream in = resource.getInputStream();
- analyzer.analyzeAll(in);
- in.close();
- }
+ final IReportGroupVisitor groupVisitor = visitor
+ .visitGroup(group.name);
+ for (final GroupElement child : group.children) {
+ createReport(groupVisitor, child);
}
- return builder.getBundle(group.name);
+ } else {
+ final IBundleCoverage bundle = createBundle(group);
+ final SourceFileCollection locator = new SourceFileCollection(
+ group.sourcefiles);
+ if (!locator.isEmpty()) {
+ checkForMissingDebugInformation(bundle);
+ }
+ visitor.visitBundle(bundle, locator);
+ }
+ }
+
+ private IBundleCoverage createBundle(final GroupElement group)
+ throws IOException {
+ final CoverageBuilder builder = new CoverageBuilder();
+ final Analyzer analyzer = new Analyzer(executionDataStore, builder);
+ for (final Iterator<?> i = group.classfiles.iterator(); i.hasNext();) {
+ final Resource resource = (Resource) i.next();
+ if (resource.isDirectory() && resource instanceof FileResource) {
+ analyzer.analyzeAll(((FileResource) resource).getFile());
+ } else {
+ final InputStream in = resource.getInputStream();
+ analyzer.analyzeAll(in);
+ in.close();
+ }
+ }
+ return builder.getBundle(group.name);
+ }
+
+ private void checkForMissingDebugInformation(final ICoverageNode node) {
+ if (node.getClassCounter().getTotalCount() > 0
+ && node.getLineCounter().getTotalCount() == 0) {
+ log(format(
+ "To enable source code annotation class files for bundle '%s' have to be compiled with debug information.",
+ node.getName()), Project.MSG_WARN);
}
}
@@ -542,50 +501,4 @@
}
}
- private void visitBundle(final IReportVisitor visitor,
- final IBundleCoverage bundledata,
- final SourceFileCollection sourceFileLocator) throws IOException {
- if (!sourceFileLocator.isEmpty()) {
- checkForMissingDebugInformation(bundledata);
- }
- for (final IPackageCoverage p : bundledata.getPackages()) {
- visitPackage(visitor.visitChild(p), p, sourceFileLocator);
- }
- }
-
- private void checkForMissingDebugInformation(final ICoverageNode node) {
- if (node.getClassCounter().getTotalCount() > 0
- && node.getLineCounter().getTotalCount() == 0) {
- log(format(
- "To enable source code annotation class files for bundle '%s' have to be compiled with debug information.",
- node.getName()), Project.MSG_WARN);
- }
- }
-
- private static void visitPackage(final IReportVisitor visitor,
- final IPackageCoverage packagedata,
- final ISourceFileLocator sourceFileLocator) throws IOException {
- visitLeafs(visitor, packagedata.getSourceFiles(), sourceFileLocator);
- for (final IClassCoverage c : packagedata.getClasses()) {
- visitClass(visitor.visitChild(c), c, sourceFileLocator);
- }
- visitor.visitEnd(sourceFileLocator);
- }
-
- private static void visitClass(final IReportVisitor visitor,
- final IClassCoverage classdata,
- final ISourceFileLocator sourceFileLocator) throws IOException {
- visitLeafs(visitor, classdata.getMethods(), sourceFileLocator);
- visitor.visitEnd(sourceFileLocator);
- }
-
- private static void visitLeafs(final IReportVisitor visitor,
- final Collection<? extends ICoverageNode> leafs,
- final ISourceFileLocator sourceFileLocator) throws IOException {
- for (final ICoverageNode l : leafs) {
- final IReportVisitor child = visitor.visitChild(l);
- child.visitEnd(sourceFileLocator);
- }
- }
-
}
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index ff2efaa..a887479 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -32,6 +32,11 @@
<li>Removed obsolete examples from documentation (Trac #141).</li>
</ul>
+<h3>API Changes</h3>
+<ul>
+ <li>Simplified reporting API (Trac #53).</li>
+</ul>
+
<h2>Release 0.5.0 (2011/01/19)</h2>
<h3>New Features</h3>
diff --git a/org.jacoco.report.test/src/org/jacoco/report/FileSingleReportOutputTest.java b/org.jacoco.report.test/src/org/jacoco/report/FileSingleReportOutputTest.java
deleted file mode 100644
index fb58957..0000000
--- a/org.jacoco.report.test/src/org/jacoco/report/FileSingleReportOutputTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-/**
- * Unit tests for {@link FileSingleReportOutput}.
- */
-public class FileSingleReportOutputTest {
-
- @Rule
- public TemporaryFolder folder = new TemporaryFolder();
-
- @Test
- public void testCreateFileWithDirectories() throws IOException {
- final File f = new File(folder.getRoot(), "a/b/c/test");
-
- final ISingleReportOutput output = new FileSingleReportOutput(f);
- final OutputStream stream = output.createFile();
- stream.write(1);
- stream.write(2);
- stream.write(3);
- stream.close();
-
- final InputStream actual = new FileInputStream(f);
- assertEquals(1, actual.read());
- assertEquals(2, actual.read());
- assertEquals(3, actual.read());
- assertEquals(-1, actual.read());
- }
-
- @Test(expected = IOException.class)
- public void testCreateFileNegative() throws IOException {
- final File d = folder.newFile("a");
- final File f = new File(d, "b/c/test");
- final ISingleReportOutput output = new FileSingleReportOutput(f);
- output.createFile();
- }
-
-}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MemoryMultiReportOutput.java b/org.jacoco.report.test/src/org/jacoco/report/MemoryMultiReportOutput.java
index 76caca0..982726b 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/MemoryMultiReportOutput.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/MemoryMultiReportOutput.java
@@ -14,6 +14,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -35,6 +36,8 @@
private final Set<String> open = new HashSet<String>();
+ private boolean closed = false;
+
public OutputStream createFile(final String path) throws IOException {
assertFalse("Duplicate output " + path, files.containsKey(path));
open.add(path);
@@ -49,6 +52,10 @@
return out;
}
+ public void close() throws IOException {
+ closed = true;
+ }
+
public void assertEmpty() {
assertEquals(Collections.emptySet(), files.keySet());
}
@@ -73,6 +80,7 @@
public void assertAllClosed() {
assertEquals(Collections.emptySet(), open);
+ assertTrue(closed);
}
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MemoryOutput.java b/org.jacoco.report.test/src/org/jacoco/report/MemoryOutput.java
new file mode 100644
index 0000000..c1f90dc
--- /dev/null
+++ b/org.jacoco.report.test/src/org/jacoco/report/MemoryOutput.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * In-memory report output for test purposes.
+ */
+public class MemoryOutput extends ByteArrayOutputStream {
+
+ private boolean closed = false;
+
+ @Override
+ public void close() throws IOException {
+ super.close();
+ closed = true;
+ }
+
+ public InputStream getContentsAsStream() {
+ return new ByteArrayInputStream(toByteArray());
+ }
+
+ public void assertClosed() {
+ assertTrue(closed);
+ }
+
+}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MemorySingleReportOutput.java b/org.jacoco.report.test/src/org/jacoco/report/MemorySingleReportOutput.java
deleted file mode 100644
index f3e1948..0000000
--- a/org.jacoco.report.test/src/org/jacoco/report/MemorySingleReportOutput.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * In-memory report output for test purposes.
- */
-public class MemorySingleReportOutput implements ISingleReportOutput {
-
- private ByteArrayOutputStream file;
-
- private boolean closed = true;
-
- public OutputStream createFile() throws IOException {
- assertNull("Duplicate output.", file);
- closed = false;
- file = new ByteArrayOutputStream() {
-
- @Override
- public void close() throws IOException {
- closed = true;
- super.close();
- }
- };
- return file;
- }
-
- public byte[] getFile() {
- assertNotNull("Missing file.", file);
- return file.toByteArray();
- }
-
- public InputStream getFileAsStream() {
- return new ByteArrayInputStream(getFile());
- }
-
- public void assertClosed() {
- assertTrue(closed);
- }
-
-}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MultiFormatterTest.java b/org.jacoco.report.test/src/org/jacoco/report/MultiFormatterTest.java
deleted file mode 100644
index 42adfe5..0000000
--- a/org.jacoco.report.test/src/org/jacoco/report/MultiFormatterTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.jacoco.core.analysis.CoverageNodeImpl;
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.core.data.ExecutionData;
-import org.jacoco.core.data.SessionInfo;
-import org.junit.Test;
-
-/**
- * Unit tests for {@link MultiFormatter}.
- */
-public class MultiFormatterTest {
-
- private static class MockFormatter implements IReportFormatter {
-
- private MockVisitor visitor;
-
- public IReportVisitor createReportVisitor(ICoverageNode root,
- List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData)
- throws IOException {
- visitor = new MockVisitor(root);
- return visitor;
- }
-
- @Override
- public String toString() {
- return visitor.toString();
- }
-
- }
-
- private static class MockVisitor implements IReportVisitor {
-
- private final String name;
-
- private final List<MockVisitor> children = new ArrayList<MockVisitor>();
-
- private boolean visitEndCalled = false;
-
- MockVisitor(ICoverageNode node) {
- name = node.getName();
- }
-
- public IReportVisitor visitChild(ICoverageNode node) throws IOException {
- assertFalse("visitEnd() already called", visitEndCalled);
- MockVisitor child = new MockVisitor(node);
- children.add(child);
- return child;
- }
-
- public void visitEnd(ISourceFileLocator sourceFileLocator)
- throws IOException {
- assertFalse("visitEnd() already called", visitEndCalled);
- visitEndCalled = true;
- }
-
- @Override
- public String toString() {
- assertTrue("visitEnd() has not been called", visitEndCalled);
- return name + children;
- }
- }
-
- private CoverageNodeImpl createNode(String name) {
- return new CoverageNodeImpl(ElementType.GROUP, name);
- }
-
- private static final String MOCK_REPORT = "Session[b1[p1[], p2[]], b2[]]";
-
- private void createMockReport(IReportFormatter formatter)
- throws IOException {
- final List<SessionInfo> sessions = Collections.emptyList();
- final Collection<ExecutionData> data = Collections.emptyList();
- IReportVisitor root = formatter.createReportVisitor(
- createNode("Session"), sessions, data);
- {
- IReportVisitor b1 = root.visitChild(createNode("b1"));
- {
- IReportVisitor p1 = b1.visitChild(createNode("p1"));
- p1.visitEnd(null);
- }
- {
- IReportVisitor p2 = b1.visitChild(createNode("p2"));
- p2.visitEnd(null);
- }
- b1.visitEnd(null);
- }
- {
- IReportVisitor b2 = root.visitChild(createNode("b2"));
- b2.visitEnd(null);
- }
- root.visitEnd(null);
- }
-
- @Test
- public void testMockFormatter() throws IOException {
- MockFormatter formatter = new MockFormatter();
- createMockReport(formatter);
- assertEquals(MOCK_REPORT, formatter.toString());
- }
-
- @Test
- public void testMultiFormatter() throws IOException {
- MockFormatter mock1 = new MockFormatter();
- MockFormatter mock2 = new MockFormatter();
- MockFormatter mock3 = new MockFormatter();
- MultiFormatter multi = new MultiFormatter();
- multi.add(mock1);
- multi.add(mock2);
- multi.add(mock3);
- createMockReport(multi);
- assertEquals(MOCK_REPORT, mock1.toString());
- assertEquals(MOCK_REPORT, mock2.toString());
- assertEquals(MOCK_REPORT, mock3.toString());
- }
-
-}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MultiReportVisitorTest.java b/org.jacoco.report.test/src/org/jacoco/report/MultiReportVisitorTest.java
new file mode 100644
index 0000000..30b2ae0
--- /dev/null
+++ b/org.jacoco.report.test/src/org/jacoco/report/MultiReportVisitorTest.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.analysis.IPackageCoverage;
+import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.SessionInfo;
+import org.jacoco.core.internal.analysis.BundleCoverageImpl;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link MultiReportVisitor}.
+ */
+public class MultiReportVisitorTest {
+
+ private static class MockVisitor extends MockGroupVisitor implements
+ IReportVisitor {
+
+ MockVisitor() {
+ super("Report");
+ }
+
+ private boolean visitInfosCalled = false;
+
+ private boolean visitEndCalled = false;
+
+ public void visitInfo(List<SessionInfo> sessionInfos,
+ Collection<ExecutionData> executionData) throws IOException {
+ visitInfosCalled = true;
+ }
+
+ public void visitEnd() throws IOException {
+ visitEndCalled = true;
+ }
+
+ @Override
+ public String toString() {
+ assertTrue("visitInfos() has not been called", visitInfosCalled);
+ assertTrue("visitEnd() has not been called", visitEndCalled);
+ return super.toString();
+ }
+
+ }
+
+ private static class MockGroupVisitor implements IReportGroupVisitor {
+
+ private final String name;
+
+ private final List<MockGroupVisitor> children = new ArrayList<MockGroupVisitor>();
+
+ MockGroupVisitor(String name) {
+ this.name = name;
+ }
+
+ public void visitBundle(IBundleCoverage bundle,
+ ISourceFileLocator locator) throws IOException {
+ children.add(new MockGroupVisitor(bundle.getName()));
+ }
+
+ public IReportGroupVisitor visitGroup(String name) throws IOException {
+ MockGroupVisitor child = new MockGroupVisitor(name);
+ children.add(child);
+ return child;
+ }
+
+ @Override
+ public String toString() {
+ return name + children;
+ }
+ }
+
+ private IBundleCoverage createBundle(String name) {
+ final Collection<IPackageCoverage> packages = Collections.emptyList();
+ return new BundleCoverageImpl(name, packages);
+ }
+
+ private static final String MOCK_REPORT = "Report[g1[b1[], b2[]], g2[]]";
+
+ private void createMockReport(IReportVisitor visitor) throws IOException {
+ final List<SessionInfo> sessions = Collections.emptyList();
+ final List<ExecutionData> executionData = Collections.emptyList();
+ visitor.visitInfo(sessions, executionData);
+ IReportGroupVisitor g1 = visitor.visitGroup("g1");
+ g1.visitBundle(createBundle("b1"), null);
+ g1.visitBundle(createBundle("b2"), null);
+ visitor.visitGroup("g2");
+ visitor.visitEnd();
+ }
+
+ @Test
+ public void testMockFormatter() throws IOException {
+ MockVisitor visitor = new MockVisitor();
+ createMockReport(visitor);
+ assertEquals(MOCK_REPORT, visitor.toString());
+ }
+
+ @Test
+ public void testMultiFormatter() throws IOException {
+ IReportVisitor mock1 = new MockVisitor();
+ IReportVisitor mock2 = new MockVisitor();
+ IReportVisitor mock3 = new MockVisitor();
+ List<IReportVisitor> visitors = Arrays.asList(mock1, mock2, mock3);
+ MultiReportVisitor multi = new MultiReportVisitor(visitors);
+ createMockReport(multi);
+ assertEquals(MOCK_REPORT, mock1.toString());
+ assertEquals(MOCK_REPORT, mock2.toString());
+ assertEquals(MOCK_REPORT, mock3.toString());
+ }
+}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java b/org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java
index c281b00..ba7dc32 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java
@@ -17,9 +17,7 @@
import java.util.Collections;
import java.util.List;
-import org.jacoco.core.analysis.CoverageNodeImpl;
import org.jacoco.core.analysis.IClassCoverage;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.analysis.IMethodCoverage;
import org.jacoco.core.analysis.IPackageCoverage;
import org.jacoco.core.analysis.ISourceFileCoverage;
@@ -27,13 +25,14 @@
import org.jacoco.core.data.SessionInfo;
import org.jacoco.core.internal.analysis.BundleCoverageImpl;
import org.jacoco.core.internal.analysis.ClassCoverageImpl;
+import org.jacoco.core.internal.analysis.CounterImpl;
import org.jacoco.core.internal.analysis.MethodCoverageImpl;
import org.jacoco.core.internal.analysis.PackageCoverageImpl;
import org.jacoco.core.internal.analysis.SourceFileCoverageImpl;
/**
* Creates a simple hierarchy of coverage nodes and feeds it into
- * {@link IReportFormatter} instances.
+ * {@link IReportVisitor} instances.
*/
public class ReportStructureTestDriver {
@@ -60,10 +59,13 @@
private final BundleCoverageImpl bundleCoverage;
- private final CoverageNodeImpl groupCoverage;
-
public ReportStructureTestDriver() {
- methodCoverage = new MethodCoverageImpl("fooMethod", "()V", null);
+ methodCoverage = new MethodCoverageImpl("fooMethod", "()V", null) {
+ {
+ instructionCounter = CounterImpl.getInstance(2, 22);
+ branchCounter = CounterImpl.getInstance(3, 33);
+ }
+ };
final ClassCoverageImpl classCoverageImpl = new ClassCoverageImpl(
"org/jacoco/example/FooClass", 1001, null, "java/lang/Object",
@@ -72,61 +74,38 @@
classCoverageImpl.addMethod(methodCoverage);
classCoverage = classCoverageImpl;
- sourceFileCoverage = new SourceFileCoverageImpl("FooClass.java",
- "org/jacoco/example");
+ final SourceFileCoverageImpl sourceFileCoverageImpl = new SourceFileCoverageImpl(
+ "FooClass.java", "org/jacoco/example");
+ sourceFileCoverageImpl.increment(classCoverage);
+ sourceFileCoverage = sourceFileCoverageImpl;
+
packageCoverage = new PackageCoverageImpl("org/jacoco/example",
Collections.singleton(classCoverage),
Collections.singleton(sourceFileCoverage));
bundleCoverage = new BundleCoverageImpl("bundle",
Collections.singleton(packageCoverage));
- groupCoverage = new CoverageNodeImpl(ElementType.GROUP, "group");
}
- public void sendGroup(IReportFormatter formatter) throws IOException {
- final IReportVisitor child = formatter.createReportVisitor(
- groupCoverage, sessions, executionData);
- sendBundle(child);
- child.visitEnd(sourceFileLocator);
+ public void sendGroup(IReportVisitor reportVisitor) throws IOException {
+ reportVisitor.visitInfo(sessions, executionData);
+ final IReportGroupVisitor group = reportVisitor.visitGroup("group");
+ sendBundle(group);
+ reportVisitor.visitEnd();
}
- public void sendGroup(IReportVisitor parent) throws IOException {
- final IReportVisitor child = parent.visitChild(groupCoverage);
- sendBundle(child);
- child.visitEnd(sourceFileLocator);
+ public void sendGroup(IReportGroupVisitor groupVisitor) throws IOException {
+ final IReportGroupVisitor group = groupVisitor.visitGroup("group");
+ sendBundle(group);
}
- public void sendBundle(IReportFormatter formatter) throws IOException {
- final IReportVisitor child = formatter.createReportVisitor(
- bundleCoverage, sessions, executionData);
- sendPackage(child);
- child.visitEnd(sourceFileLocator);
+ public void sendBundle(IReportVisitor reportVisitor) throws IOException {
+ reportVisitor.visitInfo(sessions, executionData);
+ reportVisitor.visitBundle(bundleCoverage, sourceFileLocator);
+ reportVisitor.visitEnd();
}
- public void sendBundle(IReportVisitor parent) throws IOException {
- final IReportVisitor child = parent.visitChild(bundleCoverage);
- sendPackage(child);
- child.visitEnd(sourceFileLocator);
- }
-
- public void sendPackage(IReportVisitor parent) throws IOException {
- final IReportVisitor child = parent.visitChild(packageCoverage);
- sendClass(child);
- sendSourceFile(child);
- child.visitEnd(sourceFileLocator);
- }
-
- public void sendClass(IReportVisitor parent) throws IOException {
- final IReportVisitor child = parent.visitChild(classCoverage);
- sendMethod(child);
- child.visitEnd(sourceFileLocator);
- }
-
- public void sendMethod(IReportVisitor parent) throws IOException {
- parent.visitChild(methodCoverage).visitEnd(sourceFileLocator);
- }
-
- public void sendSourceFile(IReportVisitor parent) throws IOException {
- parent.visitChild(sourceFileCoverage).visitEnd(sourceFileLocator);
+ public void sendBundle(IReportGroupVisitor groupVisitor) throws IOException {
+ groupVisitor.visitBundle(bundleCoverage, sourceFileLocator);
}
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java
index 340372b..d280dda 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java
@@ -22,14 +22,12 @@
import java.util.Collections;
import java.util.List;
-import org.jacoco.core.analysis.CoverageNodeImpl;
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.data.ExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.ILanguageNames;
+import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.MemorySingleReportOutput;
+import org.jacoco.report.MemoryOutput;
import org.jacoco.report.ReportStructureTestDriver;
import org.junit.After;
import org.junit.Before;
@@ -40,20 +38,22 @@
*/
public class CSVFormatterTest {
- private static final String HEADER = "GROUP,PACKAGE,CLASS,METHOD_COVERED,METHOD_MISSED,LINE_COVERED,LINE_MISSED,INSTRUCTION_COVERED,INSTRUCTION_MISSED,BRANCH_COVERED,BRANCH_MISSED";
+ private static final String HEADER = "GROUP,PACKAGE,CLASS,INSTRUCTION_MISSED,INSTRUCTION_COVERED,BRANCH_MISSED,BRANCH_COVERED,LINE_MISSED,LINE_COVERED,METHOD_MISSED,METHOD_COVERED";
private ReportStructureTestDriver driver;
private CSVFormatter formatter;
- private MemorySingleReportOutput output;
+ private IReportVisitor visitor;
+
+ private MemoryOutput output;
@Before
- public void setup() {
+ public void setup() throws Exception {
driver = new ReportStructureTestDriver();
formatter = new CSVFormatter();
- output = new MemorySingleReportOutput();
- formatter.setReportOutput(output);
+ output = new MemoryOutput();
+ visitor = formatter.createVisitor(output);
}
@After
@@ -61,55 +61,48 @@
output.assertClosed();
}
- @Test(expected = IllegalStateException.class)
- public void testNoReportOutput() throws IOException {
- new CSVFormatter().createReportVisitor(null, null, null);
- }
-
@Test
public void testStructureWithGroup() throws IOException {
- driver.sendGroup(formatter);
+ driver.sendGroup(visitor);
final List<String> lines = getLines();
assertEquals(HEADER, lines.get(0));
assertEquals(
- "group/bundle,org.jacoco.example,FooClass,0,1,0,0,0,0,0,0",
+ "group/bundle,org.jacoco.example,FooClass,2,22,3,33,0,0,1,0",
lines.get(1));
}
@Test
public void testStructureWithNestedGroups() throws IOException {
- final ICoverageNode root = new CoverageNodeImpl(ElementType.GROUP,
- "root");
final List<SessionInfo> sessions = Collections.emptyList();
final Collection<ExecutionData> data = Collections.emptyList();
- final IReportVisitor child = formatter.createReportVisitor(root,
- sessions, data);
- driver.sendGroup(child);
- driver.sendGroup(child);
- child.visitEnd(driver.sourceFileLocator);
+ visitor.visitInfo(sessions, data);
+ driver.sendGroup((IReportGroupVisitor) visitor);
+ driver.sendGroup((IReportGroupVisitor) visitor);
+ visitor.visitEnd();
final List<String> lines = getLines();
assertEquals(HEADER, lines.get(0));
assertEquals(
- "root/group/bundle,org.jacoco.example,FooClass,0,1,0,0,0,0,0,0",
+ "group/bundle,org.jacoco.example,FooClass,2,22,3,33,0,0,1,0",
lines.get(1));
assertEquals(
- "root/group/bundle,org.jacoco.example,FooClass,0,1,0,0,0,0,0,0",
+ "group/bundle,org.jacoco.example,FooClass,2,22,3,33,0,0,1,0",
lines.get(2));
}
@Test
public void testStructureWithBundleOnly() throws IOException {
- driver.sendBundle(formatter);
+ driver.sendBundle(visitor);
final List<String> lines = getLines();
assertEquals(HEADER, lines.get(0));
- assertEquals("bundle,org.jacoco.example,FooClass,0,1,0,0,0,0,0,0",
+ assertEquals("bundle,org.jacoco.example,FooClass,2,22,3,33,0,0,1,0",
lines.get(1));
}
@Test
public void testSetEncoding() throws Exception {
formatter.setOutputEncoding("UTF-16");
- driver.sendBundle(formatter);
+ visitor = formatter.createVisitor(output);
+ driver.sendBundle(visitor);
final List<String> lines = getLines("UTF-16");
assertEquals(HEADER, lines.get(0));
}
@@ -138,6 +131,7 @@
};
formatter.setLanguageNames(names);
assertSame(names, formatter.getLanguageNames());
+ output.close();
}
private List<String> getLines() throws IOException {
@@ -146,7 +140,7 @@
private List<String> getLines(String encoding) throws IOException {
final BufferedReader reader = new BufferedReader(new InputStreamReader(
- output.getFileAsStream(), encoding));
+ output.getContentsAsStream(), encoding));
final List<String> lines = new ArrayList<String>();
String line;
while ((line = reader.readLine()) != null) {
diff --git a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java
index 6ab7703..74c01cd 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java
@@ -11,12 +11,15 @@
*******************************************************************************/
package org.jacoco.report.csv;
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
import java.io.StringWriter;
-import org.jacoco.core.analysis.CoverageNodeImpl;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.report.IReportVisitor;
+import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.JavaNames;
+import org.jacoco.report.ReportStructureTestDriver;
import org.junit.Before;
import org.junit.Test;
@@ -25,28 +28,42 @@
*/
public class CSVGroupHandlerTest {
- private IReportVisitor handler;
+ private IReportGroupVisitor handler;
+
+ private StringWriter result;
+
+ private ReportStructureTestDriver driver;
@Before
public void setup() throws Exception {
- final DelimitedWriter dw = new DelimitedWriter(new StringWriter());
+ result = new StringWriter();
+ final DelimitedWriter dw = new DelimitedWriter(result);
final ClassRowWriter rw = new ClassRowWriter(dw, new JavaNames());
- handler = new CSVGroupHandler(rw, "group");
+ handler = new CSVGroupHandler(rw);
+ driver = new ReportStructureTestDriver();
}
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative1() throws Exception {
- handler.visitChild(new CoverageNodeImpl(ElementType.CLASS, "Foo"));
+ @Test
+ public void testVisitBundle() throws Exception {
+ driver.sendBundle(handler);
+ final BufferedReader reader = getResultReader();
+ reader.readLine();
+ assertEquals("bundle,org.jacoco.example,FooClass,2,22,3,33,0,0,1,0",
+ reader.readLine());
}
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative2() throws Exception {
- handler.visitChild(new CoverageNodeImpl(ElementType.METHOD, "Foo"));
+ @Test
+ public void testVisitGroup() throws Exception {
+ driver.sendGroup(handler);
+ final BufferedReader reader = getResultReader();
+ reader.readLine();
+ assertEquals(
+ "group/bundle,org.jacoco.example,FooClass,2,22,3,33,0,0,1,0",
+ reader.readLine());
}
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative3() throws Exception {
- handler.visitChild(new CoverageNodeImpl(ElementType.SOURCEFILE, "Foo"));
+ private BufferedReader getResultReader() {
+ return new BufferedReader(new StringReader(result.toString()));
}
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVPackageHandlerTest.java b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVPackageHandlerTest.java
deleted file mode 100644
index bbb0356..0000000
--- a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVPackageHandlerTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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.csv;
-
-import java.io.StringWriter;
-
-import org.jacoco.core.analysis.CoverageNodeImpl;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.JavaNames;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Unit tests for {@link CSVPackageHandler}.
- */
-public class CSVPackageHandlerTest {
-
- private IReportVisitor handler;
-
- @Before
- public void setup() throws Exception {
- final DelimitedWriter dw = new DelimitedWriter(new StringWriter());
- final ClassRowWriter rw = new ClassRowWriter(dw, new JavaNames());
- handler = new CSVPackageHandler(rw, "group", "package");
- }
-
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative1() throws Exception {
- handler.visitChild(new CoverageNodeImpl(ElementType.GROUP, "Foo"));
- }
-
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative2() throws Exception {
- handler.visitChild(new CoverageNodeImpl(ElementType.BUNDLE, "Foo"));
- }
-
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative3() throws Exception {
- handler.visitChild(new CoverageNodeImpl(ElementType.PACKAGE, "Foo"));
- }
-
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative4() throws Exception {
- handler.visitChild(new CoverageNodeImpl(ElementType.METHOD, "Foo"));
- }
-
-}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/csv/ClassRowWriterTest.java b/org.jacoco.report.test/src/org/jacoco/report/csv/ClassRowWriterTest.java
new file mode 100644
index 0000000..6a5b75c
--- /dev/null
+++ b/org.jacoco.report.test/src/org/jacoco/report/csv/ClassRowWriterTest.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.csv;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import org.jacoco.core.analysis.IClassCoverage;
+import org.jacoco.core.internal.analysis.ClassCoverageImpl;
+import org.jacoco.core.internal.analysis.CounterImpl;
+import org.jacoco.report.ILanguageNames;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link ClassRowWriter}.
+ */
+public class ClassRowWriterTest {
+
+ private StringWriter result;
+
+ private ClassRowWriter writer;
+
+ @Before
+ public void setup() throws Exception {
+ ILanguageNames names = new ILanguageNames() {
+ public String getClassName(String vmname, String vmsignature,
+ String vmsuperclass, String[] vminterfaces) {
+ return vmname;
+ }
+
+ public String getPackageName(String vmname) {
+ return vmname;
+ }
+
+ public String getQualifiedClassName(String vmname) {
+ throw new AssertionError();
+ }
+
+ public String getMethodName(String vmclassname,
+ String vmmethodname, String vmdesc, String vmsignature) {
+ throw new AssertionError();
+ }
+ };
+ result = new StringWriter();
+ writer = new ClassRowWriter(new DelimitedWriter(result), names);
+ }
+
+ @Test
+ public void TestHeader() throws Exception {
+ BufferedReader reader = getResultReader();
+ assertEquals(
+ "GROUP,PACKAGE,CLASS,INSTRUCTION_MISSED,INSTRUCTION_COVERED,BRANCH_MISSED,BRANCH_COVERED,LINE_MISSED,LINE_COVERED,METHOD_MISSED,METHOD_COVERED",
+ reader.readLine());
+ }
+
+ @Test
+ public void TestRow() throws Exception {
+ IClassCoverage node = new ClassCoverageImpl("test/package/Foo", 123,
+ null, "java/lang/Object", null) {
+ {
+ instructionCounter = CounterImpl.getInstance(1, 11);
+ branchCounter = CounterImpl.getInstance(2, 22);
+ lineCounter = CounterImpl.getInstance(3, 33);
+ methodCounter = CounterImpl.getInstance(4, 44);
+ classCounter = CounterImpl.getInstance(5, 55);
+ }
+ };
+ writer.writeRow("group", "test/package", node);
+ BufferedReader reader = getResultReader();
+ reader.readLine();
+ assertEquals("group,test/package,test/package/Foo,1,11,2,22,3,33,4,44",
+ reader.readLine());
+ }
+
+ private BufferedReader getResultReader() {
+ return new BufferedReader(new StringReader(result.toString()));
+ }
+
+}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java b/org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java
index 2899ab4..64e2fbb 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java
@@ -43,7 +43,6 @@
driver = new ReportStructureTestDriver();
formatter = new HTMLFormatter();
output = new MemoryMultiReportOutput();
- formatter.setReportOutput(output);
}
@After
@@ -51,14 +50,9 @@
output.assertAllClosed();
}
- @Test(expected = IllegalStateException.class)
- public void testNoReportOutput() throws IOException {
- new HTMLFormatter().createReportVisitor(null, null, null);
- }
-
@Test
public void testStructureWithGroup() throws IOException {
- driver.sendGroup(formatter);
+ driver.sendGroup(formatter.createVisitor(output));
output.assertFile("index.html");
output.assertFile("bundle/index.html");
output.assertFile("bundle/org.jacoco.example/index.html");
@@ -67,7 +61,7 @@
@Test
public void testStructureWithBundleOnly() throws IOException {
- driver.sendBundle(formatter);
+ driver.sendBundle(formatter.createVisitor(output));
output.assertFile("index.html");
output.assertFile("org.jacoco.example/index.html");
output.assertFile("org.jacoco.example/FooClass.html");
@@ -75,7 +69,7 @@
@Test
public void testDefaultEncoding() throws Exception {
- driver.sendBundle(formatter);
+ driver.sendBundle(formatter.createVisitor(output));
final BufferedReader reader = new BufferedReader(new InputStreamReader(
output.getFileAsStream("index.html"), "UTF-8"));
final String line = reader.readLine();
@@ -86,7 +80,7 @@
@Test
public void testSetEncoding() throws Exception {
formatter.setOutputEncoding("UTF-16");
- driver.sendBundle(formatter);
+ driver.sendBundle(formatter.createVisitor(output));
final BufferedReader reader = new BufferedReader(new InputStreamReader(
output.getFileAsStream("index.html"), "UTF-16"));
final String line = reader.readLine();
@@ -118,18 +112,21 @@
};
formatter.setLanguageNames(names);
assertSame(names, formatter.getLanguageNames());
+ output.close();
}
@Test
public void testGetFooterText() throws Exception {
formatter.setFooterText("Custom Footer");
assertEquals("Custom Footer", formatter.getFooterText());
+ output.close();
}
@Test
public void testGetLocale() throws Exception {
formatter.setLocale(Locale.KOREAN);
assertEquals(Locale.KOREAN, formatter.getLocale());
+ output.close();
}
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/NormalizedFileNamesTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java
similarity index 95%
rename from org.jacoco.report.test/src/org/jacoco/report/NormalizedFileNamesTest.java
rename to org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java
index 297dfb5..53faace 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/NormalizedFileNamesTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java
@@ -9,10 +9,11 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report;
+package org.jacoco.report.internal;
import static org.junit.Assert.assertEquals;
+import org.jacoco.report.internal.NormalizedFileNames;
import org.junit.Before;
import org.junit.Test;
diff --git a/org.jacoco.report.test/src/org/jacoco/report/ReportOutputFolderTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/ReportOutputFolderTest.java
similarity index 94%
rename from org.jacoco.report.test/src/org/jacoco/report/ReportOutputFolderTest.java
rename to org.jacoco.report.test/src/org/jacoco/report/internal/ReportOutputFolderTest.java
index f7d5d04..3129879 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/ReportOutputFolderTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/ReportOutputFolderTest.java
@@ -9,13 +9,14 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report;
+package org.jacoco.report.internal;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import java.io.IOException;
+import org.jacoco.report.MemoryMultiReportOutput;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -36,7 +37,8 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
@@ -58,6 +60,7 @@
root.subFolder("folderA").subFolder("folderB").createFile("test.html")
.close();
output.assertSingleFile("folderA/folderB/test.html");
+ output.close();
output.assertAllClosed();
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/LinkableStub.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/LinkableStub.java
index 805cb07..d262502 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/LinkableStub.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/LinkableStub.java
@@ -11,7 +11,7 @@
*******************************************************************************/
package org.jacoco.report.internal.html;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
/**
* Stub implementation for {@link ILinkable}.
@@ -22,7 +22,7 @@
private final String label;
private final String style;
- LinkableStub(String link, String label, String style) {
+ public LinkableStub(String link, String label, String style) {
this.link = link;
this.label = label;
this.style = style;
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/PackagePageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/PackagePageTest.java
deleted file mode 100644
index 86e63f1..0000000
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/PackagePageTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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.html;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Locale;
-
-import org.jacoco.core.analysis.CoverageNodeImpl;
-import org.jacoco.core.analysis.IClassCoverage;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.core.analysis.IPackageCoverage;
-import org.jacoco.core.analysis.ISourceFileCoverage;
-import org.jacoco.core.internal.analysis.PackageCoverageImpl;
-import org.jacoco.report.ILanguageNames;
-import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
-import org.jacoco.report.internal.html.index.IIndexUpdate;
-import org.jacoco.report.internal.html.resources.Resources;
-import org.jacoco.report.internal.html.table.Table;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Unit tests for {@link PackagePage}.
- */
-public class PackagePageTest {
-
- private MemoryMultiReportOutput output;
-
- private ReportOutputFolder root;
-
- private IHTMLReportContext context;
-
- private PackagePage page;
-
- @Before
- public void setup() {
- output = new MemoryMultiReportOutput();
- root = new ReportOutputFolder(output);
- context = new IHTMLReportContext() {
-
- public ILanguageNames getLanguageNames() {
- throw new AssertionError("Unexpected method call.");
- }
-
- public Resources getResources() {
- throw new AssertionError("Unexpected method call.");
- }
-
- public Table getTable() {
- throw new AssertionError("Unexpected method call.");
- }
-
- public String getFooterText() {
- throw new AssertionError("Unexpected method call.");
- }
-
- public ILinkable getSessionsPage() {
- throw new AssertionError("Unexpected method call.");
- }
-
- public String getOutputEncoding() {
- throw new AssertionError("Unexpected method call.");
- }
-
- public IIndexUpdate getIndexUpdate() {
- throw new AssertionError("Unexpected method call.");
- }
-
- public Locale getLocale() {
- throw new AssertionError("Unexpected method call.");
- }
- };
- Collection<IClassCoverage> classes = Collections.emptyList();
- Collection<ISourceFileCoverage> sources = Collections.emptyList();
- final IPackageCoverage node = new PackageCoverageImpl("foo", classes,
- sources);
- page = new PackagePage(node, null, root, context);
- }
-
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative1() {
- page.visitChild(new CoverageNodeImpl(ElementType.GROUP, "Foo"));
- }
-
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative2() {
- page.visitChild(new CoverageNodeImpl(ElementType.BUNDLE, "Foo"));
- }
-
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative3() {
- page.visitChild(new CoverageNodeImpl(ElementType.PACKAGE, "Foo"));
- }
-
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative4() {
- page.visitChild(new CoverageNodeImpl(ElementType.METHOD, "Foo"));
- }
-
-}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/NodePageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/NodePageTest.java
similarity index 77%
rename from org.jacoco.report.test/src/org/jacoco/report/internal/html/NodePageTest.java
rename to org.jacoco.report.test/src/org/jacoco/report/internal/html/page/NodePageTest.java
index 3104053..5067b1e 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/NodePageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/NodePageTest.java
@@ -9,9 +9,10 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
+package org.jacoco.report.internal.html.page;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
import java.io.IOException;
import java.util.Locale;
@@ -19,11 +20,13 @@
import org.jacoco.core.analysis.CoverageNodeImpl;
import org.jacoco.core.analysis.ICoverageNode;
import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.core.internal.analysis.CounterImpl;
import org.jacoco.report.ILanguageNames;
-import org.jacoco.report.IReportVisitor;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLElement;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.ILinkable;
+import org.jacoco.report.internal.html.LinkableStub;
import org.jacoco.report.internal.html.index.IIndexUpdate;
import org.jacoco.report.internal.html.resources.Resources;
import org.jacoco.report.internal.html.resources.Styles;
@@ -45,9 +48,9 @@
private CoverageNodeImpl node;
- private NodePage page;
+ private NodePage<ICoverageNode> page;
- private class TestNodePage extends NodePage {
+ private class TestNodePage extends NodePage<ICoverageNode> {
protected TestNodePage(ICoverageNode node) {
super(node, null, root, NodePageTest.this.context);
@@ -62,10 +65,6 @@
return "index.html";
}
- public IReportVisitor visitChild(ICoverageNode node) {
- throw new UnsupportedOperationException();
- }
-
}
@Before
@@ -113,22 +112,14 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
@Test
public void testGetNode() throws IOException {
- node.increment(new CoverageNodeImpl(ElementType.GROUP, "Foo") {
- {
- branchCounter = CounterImpl.getInstance(15, 8);
- }
- });
- page.visitEnd(null);
- assertEquals(node.getName(), page.getNode().getName());
- assertEquals(node.getElementType(), page.getNode().getElementType());
- assertEquals(CounterImpl.getInstance(15, 8), page.getNode()
- .getBranchCounter());
+ assertSame(node, page.getNode());
}
@Test
@@ -141,10 +132,4 @@
assertEquals("el_group", page.getLinkStyle());
}
- @Test
- public void testVisitEnd() throws IOException {
- page.visitEnd(null);
- output.assertSingleFile("index.html");
- }
-
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/ReportPageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ReportPageTest.java
similarity index 88%
rename from org.jacoco.report.test/src/org/jacoco/report/internal/html/ReportPageTest.java
rename to org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ReportPageTest.java
index 20f88ee..6e18fef 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/ReportPageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ReportPageTest.java
@@ -9,7 +9,7 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
+package org.jacoco.report.internal.html.page;
import static org.junit.Assert.assertEquals;
@@ -18,7 +18,12 @@
import org.jacoco.report.ILanguageNames;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLElement;
+import org.jacoco.report.internal.html.HTMLSupport;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.ILinkable;
+import org.jacoco.report.internal.html.LinkableStub;
import org.jacoco.report.internal.html.index.IIndexUpdate;
import org.jacoco.report.internal.html.resources.Resources;
import org.jacoco.report.internal.html.resources.Styles;
@@ -53,17 +58,6 @@
}
@Override
- protected void headExtra(HTMLElement head) throws IOException {
- super.headExtra(head);
- head.script("text/javascript", "test.js");
- }
-
- @Override
- protected String getOnload() {
- return "init()";
- }
-
- @Override
protected void content(HTMLElement body) throws IOException {
body.div("testcontent").text("Hello Test");
}
@@ -129,7 +123,8 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
@@ -141,7 +136,7 @@
@Test
public void testPageContent() throws Exception {
- page.renderDocument();
+ page.render();
final HTMLSupport support = new HTMLSupport();
final Document doc = support.parse(output.getFile("Test.html"));
@@ -149,12 +144,6 @@
assertEquals(".resources/report.css", support.findStr(doc,
"/html/head/link[@rel='stylesheet']/@href"));
- // extra head
- assertEquals("test.js", support.findStr(doc, "/html/head/script/@src"));
-
- // onload handler
- assertEquals("init()", support.findStr(doc, "/html/body/@onload"));
-
// bread crumb
assertEquals("Report", support.findStr(doc,
"/html/body/div[@class='breadcrumb']/a[1]/text()"));
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/SessionsPageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SessionsPageTest.java
similarity index 92%
rename from org.jacoco.report.test/src/org/jacoco/report/internal/html/SessionsPageTest.java
rename to org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SessionsPageTest.java
index 3fad3e4..f9fe548 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/SessionsPageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SessionsPageTest.java
@@ -9,7 +9,7 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
+package org.jacoco.report.internal.html.page;
import static org.junit.Assert.assertEquals;
@@ -25,7 +25,12 @@
import org.jacoco.report.ILanguageNames;
import org.jacoco.report.JavaNames;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLElement;
+import org.jacoco.report.internal.html.HTMLSupport;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.ILinkable;
+import org.jacoco.report.internal.html.LinkableStub;
import org.jacoco.report.internal.html.index.ElementIndex;
import org.jacoco.report.internal.html.index.IIndexUpdate;
import org.jacoco.report.internal.html.resources.Resources;
@@ -99,7 +104,8 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
@@ -128,7 +134,7 @@
public void testEmptyContent() throws Exception {
final SessionsPage page = new SessionsPage(noSessions, noExecutionData,
index, null, root, context);
- page.renderDocument();
+ page.render();
final HTMLSupport support = new HTMLSupport();
final Document doc = support.parse(output.getFile(".sessions.html"));
assertEquals("No session information available.",
@@ -145,7 +151,7 @@
sessions.add(new SessionInfo("Session-C", 0, 0));
final SessionsPage page = new SessionsPage(sessions, noExecutionData,
index, null, root, context);
- page.renderDocument();
+ page.render();
final HTMLSupport support = new HTMLSupport();
final Document doc = support.parse(output.getFile(".sessions.html"));
assertEquals("el_session", support.findStr(doc,
@@ -186,7 +192,7 @@
final SessionsPage page = new SessionsPage(noSessions, data, index,
null, root, context);
- page.renderDocument();
+ page.render();
final HTMLSupport support = new HTMLSupport();
final Document doc = support.parse(output.getFile(".sessions.html"));
assertEquals("el_class", support.findStr(doc,
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/SourceFilePageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceFilePageTest.java
similarity index 70%
rename from org.jacoco.report.test/src/org/jacoco/report/internal/html/SourceFilePageTest.java
rename to org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceFilePageTest.java
index 4575211..0d83f77 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/SourceFilePageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceFilePageTest.java
@@ -9,24 +9,24 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
+package org.jacoco.report.internal.html.page;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
import java.util.Locale;
-import org.jacoco.core.analysis.CoverageNodeImpl;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.internal.analysis.SourceFileCoverageImpl;
-import org.jacoco.report.DirectorySourceFileLocator;
import org.jacoco.report.ILanguageNames;
-import org.jacoco.report.ISourceFileLocator;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLSupport;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.ILinkable;
+import org.jacoco.report.internal.html.LinkableStub;
import org.jacoco.report.internal.html.index.IIndexUpdate;
import org.jacoco.report.internal.html.resources.Resources;
import org.jacoco.report.internal.html.resources.Styles;
@@ -47,10 +47,10 @@
private IHTMLReportContext context;
- private ISourceFileLocator locator;
+ private Reader sourceReader;
@Before
- public void setup() {
+ public void setup() throws IOException {
output = new MemoryMultiReportOutput();
root = new ReportOutputFolder(output);
final Resources resources = new Resources(root);
@@ -89,32 +89,25 @@
return Locale.ENGLISH;
}
};
- locator = new DirectorySourceFileLocator(new File("./src"), "UTF-8");
+ sourceReader = new InputStreamReader(
+ new FileInputStream(
+ "./src/org/jacoco/report/internal/html/page/SourceFilePageTest.java"),
+ "UTF-8");
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
- @Test(expected = AssertionError.class)
- public void testVisitChildNegative() {
- final SourceFileCoverageImpl node = new SourceFileCoverageImpl(
- "SourceFilePageTest.java", "org/jacoco/report/html");
- final SourceFilePage page = new SourceFilePage(node, null, root,
- context);
- page.visitChild(new CoverageNodeImpl(ElementType.CLASS, "Foo"));
- }
-
@Test
public void testContents() throws Exception {
final SourceFileCoverageImpl node = new SourceFileCoverageImpl(
"SourceFilePageTest.java", "org/jacoco/report/internal/html");
- final SourceFilePage page = new SourceFilePage(node, null, root,
- context);
- page.visitEnd(locator);
-
- assertTrue(page.exists());
+ final SourceFilePage page = new SourceFilePage(node, sourceReader,
+ null, root, context);
+ page.render();
final HTMLSupport support = new HTMLSupport();
final Document result = support.parse(output
@@ -139,16 +132,4 @@
support.findStr(result, "/html/body/pre/span[1]/@id"));
}
- @Test
- public void testNoSource() throws IOException {
- final SourceFileCoverageImpl node = new SourceFileCoverageImpl(
- "DoesNotExist.java", "org/jacoco/report/html");
- final SourceFilePage page = new SourceFilePage(node, null, root,
- context);
- page.visitEnd(locator);
-
- assertFalse(page.exists());
- output.assertEmpty();
- }
-
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/SourceHighlighterTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceHighlighterTest.java
similarity index 96%
rename from org.jacoco.report.test/src/org/jacoco/report/internal/html/SourceHighlighterTest.java
rename to org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceHighlighterTest.java
index 9f65a3e..15db391 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/SourceHighlighterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceHighlighterTest.java
@@ -9,7 +9,7 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
+package org.jacoco.report.internal.html.page;
import static org.junit.Assert.assertEquals;
@@ -20,6 +20,9 @@
import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.internal.analysis.CounterImpl;
import org.jacoco.core.internal.analysis.SourceNodeImpl;
+import org.jacoco.report.internal.html.HTMLDocument;
+import org.jacoco.report.internal.html.HTMLElement;
+import org.jacoco.report.internal.html.HTMLSupport;
import org.jacoco.report.internal.html.resources.Styles;
import org.junit.Before;
import org.junit.Test;
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/ResourcesTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/ResourcesTest.java
index 56d5202..fa7e449 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/ResourcesTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/ResourcesTest.java
@@ -17,7 +17,7 @@
import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.junit.Before;
import org.junit.Test;
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/BarColumnTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/BarColumnTest.java
index 8c1fc26..444dda7 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/BarColumnTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/BarColumnTest.java
@@ -14,6 +14,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;
@@ -24,7 +25,7 @@
import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.internal.analysis.CounterImpl;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLDocument;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.HTMLSupport;
@@ -66,7 +67,8 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/CounterColumnTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/CounterColumnTest.java
index 8430fbc..5bbdbd2 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/CounterColumnTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/CounterColumnTest.java
@@ -15,6 +15,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
@@ -26,7 +27,7 @@
import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.internal.analysis.CounterImpl;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLDocument;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.HTMLSupport;
@@ -68,7 +69,8 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/LabelColumnTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/LabelColumnTest.java
index 8c8fe7f..ed2d7cf 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/LabelColumnTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/LabelColumnTest.java
@@ -14,11 +14,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.io.IOException;
+
import org.jacoco.core.analysis.CoverageNodeImpl;
import org.jacoco.core.analysis.ICoverageNode;
import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLDocument;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.HTMLSupport;
@@ -60,7 +62,8 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/PercentageColumnTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/PercentageColumnTest.java
index 263a399..bbe963d 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/PercentageColumnTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/PercentageColumnTest.java
@@ -14,6 +14,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.io.IOException;
import java.util.Comparator;
import java.util.Locale;
@@ -23,7 +24,7 @@
import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.internal.analysis.CounterImpl;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLDocument;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.HTMLSupport;
@@ -65,7 +66,8 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/TableTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/TableTest.java
index b72956c..50d2b59 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/TableTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/TableTest.java
@@ -26,7 +26,7 @@
import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.internal.analysis.CounterImpl;
import org.jacoco.report.MemoryMultiReportOutput;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLDocument;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.HTMLSupport;
@@ -65,7 +65,8 @@
}
@After
- public void teardown() {
+ public void teardown() throws IOException {
+ output.close();
output.assertAllClosed();
}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLGroupVisitorTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLGroupVisitorTest.java
new file mode 100644
index 0000000..81e29ff
--- /dev/null
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLGroupVisitorTest.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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 static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.jacoco.report.ReportStructureTestDriver;
+import org.jacoco.report.xml.XMLFormatter;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * Unit tests for {@link XMLGroupVisitor}.
+ */
+public class XMLGroupVisitorTest {
+
+ private XMLElement root;
+
+ private StringWriter buffer;
+
+ private XMLSupport support;
+
+ private XMLGroupVisitor handler;
+
+ private ReportStructureTestDriver driver;
+
+ @Before
+ public void setup() throws Exception {
+ buffer = new StringWriter();
+ support = new XMLSupport(XMLFormatter.class);
+ root = new XMLDocument("report", "-//JACOCO//DTD Report 1.0//EN",
+ "report.dtd", "UTF-8", true, buffer);
+ root.attr("name", "Report");
+ handler = new XMLGroupVisitor(root, null);
+ driver = new ReportStructureTestDriver();
+ }
+
+ @Test
+ public void testVisitBundle() throws Exception {
+ driver.sendBundle(handler);
+ root.close();
+ final Document doc = getDocument();
+ assertEquals("bundle", support.findStr(doc, "//report/group/@name"));
+ }
+
+ @Test
+ public void testVisitGroup() throws Exception {
+ driver.sendGroup(handler);
+ root.close();
+ final Document doc = getDocument();
+ assertEquals("group", support.findStr(doc, "//report/group/@name"));
+ }
+
+ @Test
+ public void testVisitEnd() throws Exception {
+ driver.sendBundle(handler);
+ handler.visitEnd();
+ root.close();
+ final Document doc = getDocument();
+ assertEquals("33", support.findStr(doc,
+ "//report/counter[@type='BRANCH']/@covered"));
+ }
+
+ private Document getDocument() throws SAXException, IOException,
+ ParserConfigurationException {
+ return support.parse(buffer.toString());
+ }
+
+}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLReportNodeHandlerTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLReportNodeHandlerTest.java
deleted file mode 100644
index b873252..0000000
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLReportNodeHandlerTest.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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 static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.io.StringWriter;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.jacoco.core.analysis.CoverageNodeImpl;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.core.internal.analysis.CounterImpl;
-import org.jacoco.core.internal.analysis.MethodCoverageImpl;
-import org.jacoco.core.internal.analysis.SourceNodeImpl;
-import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.xml.XMLFormatter;
-import org.junit.Before;
-import org.junit.Test;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-/**
- * Unit tests for {@link XMLReportNodeHandler}.
- */
-public class XMLReportNodeHandlerTest {
-
- private XMLElement root;
-
- private StringWriter buffer;
-
- private XMLSupport support;
-
- private XMLReportNodeHandler handler;
-
- @Before
- public void setup() throws Exception {
- buffer = new StringWriter();
- support = new XMLSupport(XMLFormatter.class);
- root = new XMLDocument("report", "-//JACOCO//DTD Report 1.0//EN",
- "report.dtd", "UTF-8", true, buffer);
- handler = new XMLReportNodeHandler(root, new CoverageNodeImpl(
- ElementType.GROUP, "Sample"));
- }
-
- @Test
- public void testRoot() throws Exception {
- final Document doc = getDocument();
- assertEquals("Sample", support.findStr(doc, "//report/@name"));
- }
-
- @Test
- public void testGroup() throws Exception {
- handler.visitChild(new CoverageNodeImpl(ElementType.GROUP, "Group1"))
- .visitEnd(null);
- final Document doc = getDocument();
- assertEquals("Group1", support.findStr(doc, "//report/group/@name"));
- }
-
- @Test
- public void testCounters() throws Exception {
- final CoverageNodeImpl node = new CoverageNodeImpl(ElementType.GROUP,
- "Group1") {
- {
- classCounter = CounterImpl.getInstance(9, 1);
- methodCounter = CounterImpl.getInstance(18, 2);
- branchCounter = CounterImpl.getInstance(27, 3);
- instructionCounter = CounterImpl.getInstance(36, 4);
- lineCounter = CounterImpl.getInstance(45, 5);
- }
- };
- handler.visitChild(node).visitEnd(null);
- final Document doc = getDocument();
- assertEquals("1", support.findStr(doc,
- "//report/group/counter[@type='CLASS']/@covered"));
- assertEquals("9", support.findStr(doc,
- "//report/group/counter[@type='CLASS']/@missed"));
- assertEquals("2", support.findStr(doc,
- "//report/group/counter[@type='METHOD']/@covered"));
- assertEquals("18", support.findStr(doc,
- "//report/group/counter[@type='METHOD']/@missed"));
- assertEquals("3", support.findStr(doc,
- "//report/group/counter[@type='BRANCH']/@covered"));
- assertEquals("27", support.findStr(doc,
- "//report/group/counter[@type='BRANCH']/@missed"));
- assertEquals("4", support.findStr(doc,
- "//report/group/counter[@type='INSTRUCTION']/@covered"));
- assertEquals("36", support.findStr(doc,
- "//report/group/counter[@type='INSTRUCTION']/@missed"));
- assertEquals("5", support.findStr(doc,
- "//report/group/counter[@type='LINE']/@covered"));
- assertEquals("45", support.findStr(doc,
- "//report/group/counter[@type='LINE']/@missed"));
- }
-
- @Test
- public void testPackage() throws Exception {
- handler.visitChild(
- new CoverageNodeImpl(ElementType.PACKAGE, "org.jacoco.example"))
- .visitEnd(null);
- final Document doc = getDocument();
- assertEquals("org.jacoco.example",
- support.findStr(doc, "//report/package/@name"));
- }
-
- @Test
- public void testClass() throws Exception {
- final IReportVisitor packageHandler = handler
- .visitChild(new CoverageNodeImpl(ElementType.PACKAGE,
- "org.jacoco.example"));
- packageHandler.visitChild(new SourceNodeImpl(ElementType.CLASS, "Foo"))
- .visitEnd(null);
- packageHandler.visitEnd(null);
- final Document doc = getDocument();
- assertEquals("Foo",
- support.findStr(doc, "//report/package/class/@name"));
- }
-
- @Test
- public void testMethod() throws Exception {
- final IReportVisitor packageHandler = handler
- .visitChild(new CoverageNodeImpl(ElementType.PACKAGE,
- "org.jacoco.example"));
- final IReportVisitor classHandler = packageHandler
- .visitChild(new SourceNodeImpl(ElementType.CLASS, "Foo"));
- MethodCoverageImpl node = new MethodCoverageImpl("doit", "()V", null);
- node.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 15);
- classHandler.visitChild(node).visitEnd(null);
- classHandler.visitEnd(null);
- packageHandler.visitEnd(null);
- final Document doc = getDocument();
- assertEquals("doit",
- support.findStr(doc, "//report/package/class/method/@name"));
- assertEquals("()V",
- support.findStr(doc, "//report/package/class/method/@desc"));
- assertEquals("15",
- support.findStr(doc, "//report/package/class/method/@line"));
- }
-
- @Test
- public void testSourcefile() throws Exception {
- final IReportVisitor packageHandler = handler
- .visitChild(new CoverageNodeImpl(ElementType.PACKAGE,
- "org.jacoco.example"));
- final SourceNodeImpl node = new SourceNodeImpl(ElementType.SOURCEFILE,
- "Foo.java");
- node.increment(CounterImpl.getInstance(1, 2),
- CounterImpl.getInstance(3, 4), 12);
- packageHandler.visitChild(node).visitEnd(null);
- packageHandler.visitEnd(null);
- final Document doc = getDocument();
- assertEquals("Foo.java",
- support.findStr(doc, "//report/package/sourcefile/@name"));
- assertEquals("12",
- support.findStr(doc, "//report/package/sourcefile/line/@nr"));
- assertEquals("1",
- support.findStr(doc, "//report/package/sourcefile/line/@mi"));
- assertEquals("2",
- support.findStr(doc, "//report/package/sourcefile/line/@ci"));
- assertEquals("3",
- support.findStr(doc, "//report/package/sourcefile/line/@mb"));
- assertEquals("4",
- support.findStr(doc, "//report/package/sourcefile/line/@cb"));
- }
-
- private Document getDocument() throws SAXException, IOException,
- ParserConfigurationException {
- handler.visitEnd(null);
- return support.parse(buffer.toString());
- }
-
-}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/xml/XMLFormatterTest.java b/org.jacoco.report.test/src/org/jacoco/report/xml/XMLFormatterTest.java
index 52125ca..93cee7d 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/xml/XMLFormatterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/xml/XMLFormatterTest.java
@@ -15,19 +15,15 @@
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
-import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
-import org.jacoco.core.analysis.CoverageNodeImpl;
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
import org.jacoco.core.data.ExecutionData;
import org.jacoco.core.data.SessionInfo;
-import org.jacoco.report.MemorySingleReportOutput;
+import org.jacoco.report.IReportVisitor;
+import org.jacoco.report.MemoryOutput;
import org.jacoco.report.ReportStructureTestDriver;
import org.jacoco.report.internal.xml.XMLSupport;
import org.junit.After;
@@ -44,14 +40,19 @@
private XMLFormatter formatter;
- private MemorySingleReportOutput output;
+ private MemoryOutput output;
+
+ private List<SessionInfo> infos;
+
+ private Collection<ExecutionData> data;
@Before
public void setup() {
driver = new ReportStructureTestDriver();
formatter = new XMLFormatter();
- output = new MemorySingleReportOutput();
- formatter.setReportOutput(output);
+ output = new MemoryOutput();
+ infos = new ArrayList<SessionInfo>();
+ data = new ArrayList<ExecutionData>();
}
@After
@@ -59,20 +60,15 @@
output.assertClosed();
}
- @Test(expected = IllegalStateException.class)
- public void testNoReportOutput() throws IOException {
- new XMLFormatter().createReportVisitor(null, null, null);
- }
-
@Test
public void testSessionInfo() throws Exception {
- final List<SessionInfo> infos = new ArrayList<SessionInfo>();
infos.add(new SessionInfo("session-1", 12345, 67890));
infos.add(new SessionInfo("session-2", 1, 2));
infos.add(new SessionInfo("session-3", 1, 2));
- ICoverageNode node = new CoverageNodeImpl(ElementType.GROUP, "Sample");
- final Collection<ExecutionData> data = Collections.emptyList();
- formatter.createReportVisitor(node, infos, data).visitEnd(null);
+ final IReportVisitor visitor = formatter.createVisitor(output);
+ visitor.visitInfo(infos, data);
+ visitor.visitGroup("foo");
+ visitor.visitEnd();
assertPathMatches("session-1", "/report/sessioninfo[1]/@id");
assertPathMatches("12345", "/report/sessioninfo[1]/@start");
assertPathMatches("67890", "/report/sessioninfo[1]/@dump");
@@ -82,7 +78,9 @@
@Test
public void testStructureWithGroup() throws Exception {
- driver.sendGroup(formatter);
+ final IReportVisitor visitor = formatter.createVisitor(output);
+ visitor.visitInfo(infos, data);
+ driver.sendGroup(visitor);
assertPathMatches("group", "/report/@name");
assertPathMatches("bundle", "/report/group/@name");
assertPathMatches("org/jacoco/example", "/report/group/package/@name");
@@ -90,23 +88,29 @@
"/report/group/package/class/@name");
assertPathMatches("fooMethod",
"/report/group/package/class/method/@name");
+ assertPathMatches("2", "report/counter[@type='INSTRUCTION']/@missed");
}
@Test
public void testStructureWithBundleOnly() throws Exception {
- driver.sendBundle(formatter);
+ final IReportVisitor visitor = formatter.createVisitor(output);
+ visitor.visitInfo(infos, data);
+ driver.sendBundle(visitor);
assertPathMatches("bundle", "/report/@name");
assertPathMatches("org/jacoco/example", "/report/package/@name");
assertPathMatches("org/jacoco/example/FooClass",
"/report/package/class/@name");
assertPathMatches("fooMethod", "/report/package/class/method/@name");
+ assertPathMatches("33", "report/counter[@type='BRANCH']/@covered");
}
@Test
public void testDefaultEncoding() throws Exception {
- driver.sendBundle(formatter);
+ final IReportVisitor visitor = formatter.createVisitor(output);
+ visitor.visitInfo(infos, data);
+ driver.sendBundle(visitor);
final BufferedReader reader = new BufferedReader(new InputStreamReader(
- output.getFileAsStream(), "UTF-8"));
+ output.getContentsAsStream(), "UTF-8"));
final String line = reader.readLine();
assertTrue(line,
line.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\""));
@@ -115,9 +119,11 @@
@Test
public void testSetEncoding() throws Exception {
formatter.setOutputEncoding("UTF-16");
- driver.sendBundle(formatter);
+ final IReportVisitor visitor = formatter.createVisitor(output);
+ visitor.visitInfo(infos, data);
+ driver.sendBundle(visitor);
final BufferedReader reader = new BufferedReader(new InputStreamReader(
- output.getFileAsStream(), "UTF-16"));
+ output.getContentsAsStream(), "UTF-16"));
final String line = reader.readLine();
assertTrue(line,
line.startsWith("<?xml version=\"1.0\" encoding=\"UTF-16\""));
@@ -126,7 +132,7 @@
private void assertPathMatches(String expected, String path)
throws Exception {
XMLSupport support = new XMLSupport(XMLFormatter.class);
- Document document = support.parse(output.getFile());
+ Document document = support.parse(output.toByteArray());
assertEquals(expected, support.findStr(document, path));
}
diff --git a/org.jacoco.report/src/org/jacoco/report/FileMultiReportOutput.java b/org.jacoco.report/src/org/jacoco/report/FileMultiReportOutput.java
index 1bcd33d..0df466c 100644
--- a/org.jacoco.report/src/org/jacoco/report/FileMultiReportOutput.java
+++ b/org.jacoco.report/src/org/jacoco/report/FileMultiReportOutput.java
@@ -46,4 +46,8 @@
return new BufferedOutputStream(new FileOutputStream(file));
}
+ public void close() throws IOException {
+ // nothing to do here
+ }
+
}
diff --git a/org.jacoco.report/src/org/jacoco/report/FileSingleReportOutput.java b/org.jacoco.report/src/org/jacoco/report/FileSingleReportOutput.java
deleted file mode 100644
index 72aeb9a..0000000
--- a/org.jacoco.report/src/org/jacoco/report/FileSingleReportOutput.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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;
-
-import static java.lang.String.format;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Implementation of {@link ISingleReportOutput} that writes the file directly
- * to a given location.
- */
-public class FileSingleReportOutput implements ISingleReportOutput {
-
- private final File file;
-
- /**
- * Creates a new instance for document output to the given location.
- *
- * @param file
- */
- public FileSingleReportOutput(final File file) {
- this.file = file;
- }
-
- public OutputStream createFile() throws IOException {
- final File parent = file.getParentFile();
- parent.mkdirs();
- if (!parent.isDirectory()) {
- throw new IOException(format("Can't create directory %s.", parent));
- }
- return new BufferedOutputStream(new FileOutputStream(file));
- }
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/IMultiReportOutput.java b/org.jacoco.report/src/org/jacoco/report/IMultiReportOutput.java
index f4f3a90..a179fa8 100644
--- a/org.jacoco.report/src/org/jacoco/report/IMultiReportOutput.java
+++ b/org.jacoco.report/src/org/jacoco/report/IMultiReportOutput.java
@@ -31,4 +31,12 @@
*/
public OutputStream createFile(String path) throws IOException;
+ /**
+ * Closes the underlying resource container.
+ *
+ * @throws IOException
+ * if closing fails
+ */
+ public void close() throws IOException;
+
}
diff --git a/org.jacoco.report/src/org/jacoco/report/IReportFormatter.java b/org.jacoco.report/src/org/jacoco/report/IReportFormatter.java
deleted file mode 100644
index 003c96f..0000000
--- a/org.jacoco.report/src/org/jacoco/report/IReportFormatter.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.List;
-
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.data.ExecutionData;
-import org.jacoco.core.data.SessionInfo;
-
-/**
- * Interface for all implementations that produce a particular report format.
- */
-public interface IReportFormatter {
-
- /**
- * Creates a visitor for root of a coverage data tree.
- *
- * @param root
- * report root node
- * @param sessionInfos
- * list of chronological ordered {@link SessionInfo} objects
- * where execution data has been collected for this report.
- * @param executionData
- * collection of all {@link ExecutionData} objects that are
- * considered for this report
- *
- * @return visitor for the root node
- * @throws IOException
- */
- public IReportVisitor createReportVisitor(ICoverageNode root,
- List<SessionInfo> sessionInfos,
- Collection<ExecutionData> executionData) throws IOException;
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/IReportGroupVisitor.java b/org.jacoco.report/src/org/jacoco/report/IReportGroupVisitor.java
new file mode 100644
index 0000000..d67bc66
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/IReportGroupVisitor.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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;
+
+import java.io.IOException;
+
+import org.jacoco.core.analysis.IBundleCoverage;
+
+/**
+ * Output-Interface for hierarchical report structures. To allow sequential
+ * processing and save memory the group structure has to be traversed in a
+ * "deep first" fashion. The interface is implemented by the report formatters
+ * and can be used to emit coverage report structures.
+ *
+ * The following constraints apply in using {@link IReportGroupVisitor} instances:
+ *
+ * <ul>
+ * <li>A visitor instance can be used to either submit bundles (
+ * {@link #visitBundle(IBundleCoverage, ISourceFileLocator)}) or groups
+ * {@link #visitGroup(String)}). Bundles and groups are not allowed for the same
+ * visitor.</li>
+ * <li>When creating nested groups with {@link #visitGroup(String)} the
+ * hierarchy has to be processed in a "deep first" manner.</li>
+ * </ul>
+ */
+public interface IReportGroupVisitor {
+
+ /**
+ * Called to add a bundle to the the report.
+ *
+ * @param bundle
+ * a bundle to include in the report
+ * @param locator
+ * source locator for this bundle
+ * @throws IOException
+ * in case of IO problems with the report writer
+ */
+ void visitBundle(IBundleCoverage bundle, ISourceFileLocator locator)
+ throws IOException;
+
+ /**
+ * Called to add a new group to the report. The returned
+ * {@link IReportGroupVisitor} instance can be used to add nested bundles or
+ * groups. The content of the group has to be completed before this or any
+ * parent visitor can be used again ("deep first").
+ *
+ * @param name
+ * name of the group
+ * @return visitor for the group's content
+ * @throws IOException
+ * in case of IO problems with the report writer
+ */
+ IReportGroupVisitor visitGroup(String name) throws IOException;
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java b/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
index 0135fcd..5821a61 100644
--- a/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
@@ -12,54 +12,41 @@
package org.jacoco.report;
import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
-import org.jacoco.core.analysis.ICoverageNode;
+import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.SessionInfo;
/**
- * Output-Interface for hierarchical coverage data information. To allow data
- * streaming and to save memory {@link ICoverageNode}s are traversed in a
- * deep-first fashion. The interface is implemented by the different report
- * writers.
+ * Interface for all implementations to retrieve structured report data. Unlike
+ * nested {@link IReportGroupVisitor} instances the root visitor accepts exactly one
+ * bundle or group.
*/
-public interface IReportVisitor {
+public interface IReportVisitor extends IReportGroupVisitor {
/**
- * Visitor without any operation.
+ * Initializes the report with global information. This method has to be
+ * called before any other method can be called.
+ *
+ * @param sessionInfos
+ * list of chronological ordered {@link SessionInfo} objects
+ * where execution data has been collected for this report.
+ * @param executionData
+ * collection of all {@link ExecutionData} objects that are
+ * considered for this report
+ * @throws IOException
+ * in case of IO problems with the report writer
*/
- public static final IReportVisitor NOP = new IReportVisitor() {
-
- public IReportVisitor visitChild(final ICoverageNode node) {
- return NOP;
- }
-
- public void visitEnd(final ISourceFileLocator sourceFileLocator) {
- }
-
- };
+ public void visitInfo(List<SessionInfo> sessionInfos,
+ Collection<ExecutionData> executionData) throws IOException;
/**
- * Called for every direct child.
- *
- * @param node
- * Node for the child in the implementation class specific to
- * this type. The counters are may yet be populated.
- *
- * @return visitor instance for processing the child node
+ * Has to be called after all report data has been emitted.
*
* @throws IOException
* in case of IO problems with the report writer
*/
- IReportVisitor visitChild(ICoverageNode node) throws IOException;
-
- /**
- * Called at the very end, when all child node have been processed and the
- * counters for this node are properly populated.
- *
- * @param sourceFileLocator
- * source file locator valid for this node
- * @throws IOException
- * in case of IO problems with the report writer
- */
- void visitEnd(ISourceFileLocator sourceFileLocator) throws IOException;
+ public void visitEnd() throws IOException;
}
diff --git a/org.jacoco.report/src/org/jacoco/report/ISingleReportOutput.java b/org.jacoco.report/src/org/jacoco/report/ISingleReportOutput.java
deleted file mode 100644
index 89eb0f1..0000000
--- a/org.jacoco.report/src/org/jacoco/report/ISingleReportOutput.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Interface to emit a single binary files.
- */
-public interface ISingleReportOutput {
-
- /**
- * Creates the output file. The returned {@link OutputStream} has to be
- * closed.
- *
- * @return output for the content
- * @throws IOException
- * if the creation fails
- */
- public OutputStream createFile() throws IOException;
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/MultiFormatter.java b/org.jacoco.report/src/org/jacoco/report/MultiFormatter.java
deleted file mode 100644
index 278047a..0000000
--- a/org.jacoco.report/src/org/jacoco/report/MultiFormatter.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.data.ExecutionData;
-import org.jacoco.core.data.SessionInfo;
-
-/**
- * A formatter that is composed from multiple other formatters. This can be used
- * to create more than one report format in one run.
- */
-public class MultiFormatter implements IReportFormatter {
-
- private final List<IReportFormatter> formatters = new ArrayList<IReportFormatter>();
-
- /**
- * Adds the given formatter to the processing chain.
- *
- * @param formatter
- * formatter to add
- */
- public void add(final IReportFormatter formatter) {
- formatters.add(formatter);
- }
-
- public IReportVisitor createReportVisitor(final ICoverageNode root,
- final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData) throws IOException {
- final List<IReportVisitor> visitors = new ArrayList<IReportVisitor>();
- for (final IReportFormatter f : formatters) {
- visitors.add(f.createReportVisitor(root, sessionInfos,
- executionData));
- }
- return new MultiVisitor(visitors);
- }
-
- private static class MultiVisitor implements IReportVisitor {
-
- private final List<IReportVisitor> visitors;
-
- MultiVisitor(final List<IReportVisitor> visitors) {
- this.visitors = visitors;
- }
-
- public IReportVisitor visitChild(final ICoverageNode node)
- throws IOException {
- final List<IReportVisitor> children = new ArrayList<IReportVisitor>();
- for (final IReportVisitor v : visitors) {
- children.add(v.visitChild(node));
- }
- return new MultiVisitor(children);
- }
-
- public void visitEnd(final ISourceFileLocator sourceFileLocator)
- throws IOException {
- for (final IReportVisitor v : visitors) {
- v.visitEnd(sourceFileLocator);
- }
- }
- }
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java b/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java
new file mode 100644
index 0000000..a3210a3
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.SessionInfo;
+
+/**
+ * A report visitor that is composed from multiple other visitors. This can be
+ * used to create more than one report format in one run.
+ */
+public class MultiReportVisitor extends MultiGroupVisitor implements
+ IReportVisitor {
+
+ private final List<IReportVisitor> visitors;
+
+ /**
+ * New visitor delegating to all given visitors.
+ *
+ * @param visitors
+ * visitors to delegate to
+ */
+ public MultiReportVisitor(final List<IReportVisitor> visitors) {
+ super(visitors);
+ this.visitors = visitors;
+ }
+
+ public void visitInfo(final List<SessionInfo> sessionInfos,
+ final Collection<ExecutionData> executionData) throws IOException {
+ for (final IReportVisitor v : visitors) {
+ v.visitInfo(sessionInfos, executionData);
+ }
+ }
+
+ public void visitEnd() throws IOException {
+ for (final IReportVisitor v : visitors) {
+ v.visitEnd();
+ }
+ }
+
+}
+
+class MultiGroupVisitor implements IReportGroupVisitor {
+
+ private final List<? extends IReportGroupVisitor> visitors;
+
+ MultiGroupVisitor(final List<? extends IReportGroupVisitor> visitors) {
+ this.visitors = visitors;
+ }
+
+ public void visitBundle(final IBundleCoverage bundle,
+ final ISourceFileLocator locator) throws IOException {
+ for (final IReportGroupVisitor v : visitors) {
+ v.visitBundle(bundle, locator);
+ }
+ }
+
+ public IReportGroupVisitor visitGroup(final String name) throws IOException {
+ final List<IReportGroupVisitor> children = new ArrayList<IReportGroupVisitor>();
+ for (final IReportGroupVisitor v : visitors) {
+ children.add(v.visitGroup(name));
+ }
+ return new MultiGroupVisitor(children);
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/ZipMultiReportOutput.java b/org.jacoco.report/src/org/jacoco/report/ZipMultiReportOutput.java
index a08545a..b92344d 100644
--- a/org.jacoco.report/src/org/jacoco/report/ZipMultiReportOutput.java
+++ b/org.jacoco.report/src/org/jacoco/report/ZipMultiReportOutput.java
@@ -36,6 +36,16 @@
this.zip = zip;
}
+ /**
+ * Creates a new instance based on the given {@link OutputStream}.
+ *
+ * @param out
+ * stream to write file entries to
+ */
+ public ZipMultiReportOutput(final OutputStream out) {
+ this.zip = new ZipOutputStream(out);
+ }
+
public OutputStream createFile(final String path) throws IOException {
if (currentEntry != null) {
currentEntry.close();
@@ -46,6 +56,10 @@
return currentEntry;
}
+ public void close() throws IOException {
+ zip.close();
+ }
+
private final class EntryOutput extends OutputStream {
private boolean closed = false;
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java b/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
index 2e047f5..033ffb9 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
@@ -12,64 +12,27 @@
package org.jacoco.report.csv;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Collection;
import java.util.List;
-import org.jacoco.core.analysis.ICoverageNode;
import org.jacoco.core.data.ExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.ILanguageNames;
-import org.jacoco.report.IReportFormatter;
import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.ISingleReportOutput;
-import org.jacoco.report.ISourceFileLocator;
import org.jacoco.report.JavaNames;
/**
* Report formatter that will create a single CSV file. By default the filename
* used will be the name of the session.
*/
-public class CSVFormatter implements IReportFormatter {
-
- private ISingleReportOutput output;
+public class CSVFormatter {
private ILanguageNames languageNames = new JavaNames();
private String outputEncoding = "UTF-8";
- public IReportVisitor createReportVisitor(final ICoverageNode root,
- final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData) throws IOException {
-
- if (output == null) {
- throw new IllegalStateException("No report output set.");
- }
- final DelimitedWriter writer = new DelimitedWriter(
- new OutputStreamWriter(output.createFile(), outputEncoding));
- final ClassRowWriter rowWriter = new ClassRowWriter(writer,
- languageNames);
- return new CSVGroupHandler(rowWriter, root.getName()) {
- @Override
- public void visitEnd(final ISourceFileLocator sourceFileLocator)
- throws IOException {
- writer.close();
- super.visitEnd(sourceFileLocator);
- }
- };
- }
-
- /**
- * Sets the report output callback for this report formatter. This is a
- * mandatory property.
- *
- * @param output
- * file output
- */
- public void setReportOutput(final ISingleReportOutput output) {
- this.output = output;
- }
-
/**
* Sets the implementation for language name display. Java language names
* are defined by default.
@@ -100,4 +63,37 @@
this.outputEncoding = outputEncoding;
}
+ /**
+ * Creates a new visitor to write a report to the given stream.
+ *
+ * @param output
+ * output stream 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 OutputStream output)
+ throws IOException {
+ final DelimitedWriter writer = new DelimitedWriter(
+ new OutputStreamWriter(output, outputEncoding));
+ final ClassRowWriter rowWriter = new ClassRowWriter(writer,
+ languageNames);
+ class Visitor extends CSVGroupHandler implements IReportVisitor {
+ Visitor() {
+ super(rowWriter);
+ }
+
+ public void visitInfo(final List<SessionInfo> sessionInfos,
+ final Collection<ExecutionData> executionData)
+ throws IOException {
+ // Info not used for CSV report
+ }
+
+ public void visitEnd() throws IOException {
+ writer.close();
+ }
+ }
+ return new Visitor();
+ }
+
}
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/CSVGroupHandler.java b/org.jacoco.report/src/org/jacoco/report/csv/CSVGroupHandler.java
index 25ebf31..b10caeb 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/CSVGroupHandler.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/CSVGroupHandler.java
@@ -11,44 +11,49 @@
*******************************************************************************/
package org.jacoco.report.csv;
-import static java.lang.String.format;
-
import java.io.IOException;
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.report.IReportVisitor;
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.analysis.IClassCoverage;
+import org.jacoco.core.analysis.IPackageCoverage;
+import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.ISourceFileLocator;
/**
* Report visitor that handles coverage information for groups.
*/
-class CSVGroupHandler implements IReportVisitor {
+class CSVGroupHandler implements IReportGroupVisitor {
private final ClassRowWriter writer;
private final String groupName;
- public CSVGroupHandler(final ClassRowWriter writer, final String groupName) {
+ public CSVGroupHandler(final ClassRowWriter writer) {
+ this(writer, null);
+ }
+
+ private CSVGroupHandler(final ClassRowWriter writer, final String groupName) {
this.writer = writer;
this.groupName = groupName;
}
- public IReportVisitor visitChild(final ICoverageNode node)
- throws IOException {
- final ElementType type = node.getElementType();
- switch (type) {
- case PACKAGE:
- return new CSVPackageHandler(writer, groupName, node.getName());
- case GROUP:
- case BUNDLE:
- return new CSVGroupHandler(writer, groupName + "/" + node.getName());
+ public void visitBundle(final IBundleCoverage bundle,
+ final ISourceFileLocator locator) throws IOException {
+ final String groupName = appendName(bundle.getName());
+ for (final IPackageCoverage p : bundle.getPackages()) {
+ final String packageName = p.getName();
+ for (final IClassCoverage c : p.getClasses()) {
+ writer.writeRow(groupName, packageName, c);
+ }
}
- throw new AssertionError(format("Unexpected child node %s.", type));
}
- public void visitEnd(final ISourceFileLocator sourceFileLocator)
- throws IOException {
+ public IReportGroupVisitor visitGroup(final String name) throws IOException {
+ return new CSVGroupHandler(writer, appendName(name));
+ }
+
+ private String appendName(final String name) {
+ return groupName == null ? name : (groupName + "/" + name);
}
}
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/CSVPackageHandler.java b/org.jacoco.report/src/org/jacoco/report/csv/CSVPackageHandler.java
deleted file mode 100644
index 725df71..0000000
--- a/org.jacoco.report/src/org/jacoco/report/csv/CSVPackageHandler.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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:
- * Brock Janiczak - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.report.csv;
-
-import static java.lang.String.format;
-
-import java.io.IOException;
-
-import org.jacoco.core.analysis.IClassCoverage;
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.ISourceFileLocator;
-
-/**
- * Report visitor that handles coverage information for packages.
- */
-class CSVPackageHandler implements IReportVisitor {
-
- private final ClassRowWriter writer;
-
- private final String groupName;
-
- private final String packageName;
-
- public CSVPackageHandler(final ClassRowWriter writer,
- final String groupName, final String packageName) {
- this.writer = writer;
- this.groupName = groupName;
- this.packageName = packageName;
- }
-
- public IReportVisitor visitChild(final ICoverageNode node)
- throws IOException {
- final ElementType type = node.getElementType();
- switch (type) {
- case CLASS:
- final IClassCoverage classNode = (IClassCoverage) node;
- writer.writeRow(groupName, packageName, classNode);
- return IReportVisitor.NOP;
- case SOURCEFILE:
- return IReportVisitor.NOP;
- }
- throw new AssertionError(format("Unexpected child node %s.", type));
- }
-
- public void visitEnd(final ISourceFileLocator sourceFileLocator) {
- }
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/ClassRowWriter.java b/org.jacoco.report/src/org/jacoco/report/csv/ClassRowWriter.java
index 17f2cfd..25b3e27 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/ClassRowWriter.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/ClassRowWriter.java
@@ -24,8 +24,9 @@
*/
class ClassRowWriter {
- private static final CounterEntity[] COUNTERS = { CounterEntity.METHOD,
- CounterEntity.LINE, CounterEntity.INSTRUCTION, CounterEntity.BRANCH };
+ private static final CounterEntity[] COUNTERS = {
+ CounterEntity.INSTRUCTION, CounterEntity.BRANCH,
+ CounterEntity.LINE, CounterEntity.METHOD };
private final DelimitedWriter writer;
@@ -52,8 +53,8 @@
private void writeHeader() throws IOException {
writer.write("GROUP", "PACKAGE", "CLASS");
for (final CounterEntity entity : COUNTERS) {
- writer.write(entity.name() + "_COVERED");
writer.write(entity.name() + "_MISSED");
+ writer.write(entity.name() + "_COVERED");
}
writer.nextLine();
}
@@ -81,8 +82,8 @@
for (final CounterEntity entity : COUNTERS) {
final ICounter counter = node.getCounter(entity);
- writer.write(counter.getCoveredCount());
writer.write(counter.getMissedCount());
+ writer.write(counter.getCoveredCount());
}
writer.nextLine();
diff --git a/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java b/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
index 62bded5..30ea239 100644
--- a/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
@@ -22,23 +22,25 @@
import java.util.List;
import java.util.Locale;
-import org.jacoco.core.analysis.ICoverageNode;
+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.IReportFormatter;
+import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.IReportVisitor;
import org.jacoco.report.ISourceFileLocator;
import org.jacoco.report.JavaNames;
-import org.jacoco.report.ReportOutputFolder;
-import org.jacoco.report.internal.html.GroupPage;
+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.SessionsPage;
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;
@@ -50,9 +52,7 @@
/**
* Formatter for coverage reports in multiple HTML pages.
*/
-public class HTMLFormatter implements IReportFormatter, IHTMLReportContext {
-
- private IMultiReportOutput output;
+public class HTMLFormatter implements IHTMLReportContext {
private ILanguageNames languageNames = new JavaNames();
@@ -77,17 +77,6 @@
}
/**
- * Defines the output for files created by the formatter. This is a
- * mandatory property.
- *
- * @param output
- * file output
- */
- public void setReportOutput(final IMultiReportOutput output) {
- this.output = output;
- }
-
- /**
* Sets the implementation for language name display. Java language names
* are defined by default.
*
@@ -191,34 +180,69 @@
return locale;
}
- // === IReportFormatter ===
-
- public IReportVisitor createReportVisitor(final ICoverageNode rootNode,
- final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData) throws IOException {
- if (output == null) {
- throw new IllegalStateException("No report output set.");
- }
+ /**
+ * 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);
- final GroupPage rootpage = new GroupPage(rootNode, null, root, this) {
- @Override
- public String getLinkStyle() {
- return Styles.EL_REPORT;
+ 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;
}
- @Override
- public void visitEnd(final ISourceFileLocator sourceFileLocator)
+ public void visitBundle(final IBundleCoverage bundle,
+ final ISourceFileLocator locator) throws IOException {
+ final BundlePage page = new BundlePage(bundle, null, locator,
+ root, HTMLFormatter.this) {
+ @Override
+ public String getLinkStyle() {
+ return Styles.EL_REPORT;
+ }
+ };
+ createSessionsPage(page);
+ page.render();
+ }
+
+ public IReportGroupVisitor visitGroup(final String name)
throws IOException {
- super.visitEnd(sourceFileLocator);
- sessionsPage.renderDocument();
+ 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();
}
};
- sessionsPage = new SessionsPage(sessionInfos, executionData, index,
- rootpage, root, this);
- return rootpage;
}
-
}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/AbstractGroupVisitor.java b/org.jacoco.report/src/org/jacoco/report/internal/AbstractGroupVisitor.java
new file mode 100644
index 0000000..5c1b6a8
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/AbstractGroupVisitor.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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;
+
+import java.io.IOException;
+
+import org.jacoco.core.analysis.CoverageNodeImpl;
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.analysis.ICoverageNode.ElementType;
+import org.jacoco.report.IReportGroupVisitor;
+import org.jacoco.report.ISourceFileLocator;
+
+/**
+ * Internal base visitor to calculate group counter summaries for hierarchical
+ * reports.
+ */
+public abstract class AbstractGroupVisitor implements IReportGroupVisitor {
+
+ /** coverage node for this group to total counters */
+ protected final CoverageNodeImpl total;
+
+ private AbstractGroupVisitor lastChild;
+
+ /**
+ * Creates a new group with the given name.
+ *
+ * @param name
+ * name for the coverage node created internally
+ */
+ protected AbstractGroupVisitor(final String name) {
+ total = new CoverageNodeImpl(ElementType.GROUP, name);
+ }
+
+ public final void visitBundle(final IBundleCoverage bundle,
+ final ISourceFileLocator locator) throws IOException {
+ total.increment(bundle);
+ handleBundle(bundle, locator);
+ }
+
+ /**
+ * Called to handle the given bundle in a specific way.
+ *
+ * @param bundle
+ * @param locator
+ * @throws IOException
+ */
+ protected abstract void handleBundle(IBundleCoverage bundle,
+ ISourceFileLocator locator) throws IOException;
+
+ public final IReportGroupVisitor visitGroup(final String name)
+ throws IOException {
+ if (lastChild != null) {
+ lastChild.visitEnd();
+ total.increment(lastChild.total);
+ }
+ lastChild = handleGroup(name);
+ return lastChild;
+ }
+
+ /**
+ * Called to handle a group with the given name in a specific way.
+ *
+ * @param name
+ * @return created child group
+ * @throws IOException
+ */
+ protected abstract AbstractGroupVisitor handleGroup(final String name)
+ throws IOException;
+
+ /**
+ * Must be called at the end of every group.
+ *
+ * @throws IOException
+ */
+ public final void visitEnd() throws IOException {
+ if (lastChild != null) {
+ lastChild.visitEnd();
+ total.increment(lastChild.total);
+ }
+ handleEnd();
+ }
+
+ /**
+ * Called to handle the end of this group in a specific way.
+ *
+ * @throws IOException
+ */
+ protected abstract void handleEnd() throws IOException;
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/NormalizedFileNames.java b/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java
similarity index 98%
rename from org.jacoco.report/src/org/jacoco/report/NormalizedFileNames.java
rename to org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java
index a212659..a5723d2 100644
--- a/org.jacoco.report/src/org/jacoco/report/NormalizedFileNames.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java
@@ -9,7 +9,7 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report;
+package org.jacoco.report.internal;
import java.util.BitSet;
import java.util.HashMap;
diff --git a/org.jacoco.report/src/org/jacoco/report/ReportOutputFolder.java b/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java
similarity index 97%
rename from org.jacoco.report/src/org/jacoco/report/ReportOutputFolder.java
rename to org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java
index 41ec26e..230d02b 100644
--- a/org.jacoco.report/src/org/jacoco/report/ReportOutputFolder.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java
@@ -9,13 +9,15 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report;
+package org.jacoco.report.internal;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
+import org.jacoco.report.IMultiReportOutput;
+
/**
* Logical representation of a folder in the output structure. This utility
* ensures valid and unique file names and helps to create relative links.
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/ClassPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/ClassPage.java
deleted file mode 100644
index 5383a37..0000000
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/ClassPage.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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.html;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.jacoco.core.analysis.IClassCoverage;
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.IMethodCoverage;
-import org.jacoco.core.analysis.ISourceNode;
-import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.ReportOutputFolder;
-import org.jacoco.report.internal.html.resources.Resources;
-import org.jacoco.report.internal.html.resources.Styles;
-import org.jacoco.report.internal.html.table.ITableItem;
-
-/**
- * Page showing coverage information for a class as a table of methods. The
- * methods are linked to the corresponding source file.
- */
-public class ClassPage extends NodePage {
-
- private class MethodItem implements ITableItem {
-
- private final IMethodCoverage node;
-
- MethodItem(final IMethodCoverage node) {
- this.node = node;
- }
-
- public String getLinkLabel() {
- return context.getLanguageNames().getMethodName(
- ClassPage.this.getNode().getName(), node.getName(),
- node.getDesc(), node.getSignature());
- }
-
- public String getLinkStyle() {
- return Styles.EL_METHOD;
- }
-
- public String getLink(final ReportOutputFolder base) {
- final SourceFilePage sourceFilePage = sourceFiles
- .get(sourceFileName);
- if (sourceFilePage == null || !sourceFilePage.exists()) {
- return null;
- }
- final String link = sourceFilePage.getLink(base);
- final ISourceNode source = node;
- final int first = source.getFirstLine();
- return first != ISourceNode.UNKNOWN_LINE ? link + "#L" + first
- : link;
- }
-
- public ICoverageNode getNode() {
- return node;
- }
-
- }
-
- private final List<MethodItem> methods = new ArrayList<MethodItem>();
-
- private final Map<String, SourceFilePage> sourceFiles;
-
- private final String label;
-
- private final String sourceFileName;
-
- /**
- * Creates a new visitor in the given context.
- *
- * @param classNode
- * @param parent
- * @param sourceFiles
- * @param folder
- * @param context
- */
- public ClassPage(final IClassCoverage classNode, final ReportPage parent,
- final Map<String, SourceFilePage> sourceFiles,
- final ReportOutputFolder folder, final IHTMLReportContext context) {
- super(classNode, parent, folder, context);
- this.sourceFiles = sourceFiles;
- this.label = context.getLanguageNames().getClassName(
- classNode.getName(), classNode.getSignature(),
- classNode.getSuperName(), classNode.getInterfaceNames());
- this.sourceFileName = classNode.getSourceFileName();
- context.getIndexUpdate().addClass(this, classNode.getId());
- }
-
- public IReportVisitor visitChild(final ICoverageNode node) {
- methods.add(new MethodItem((IMethodCoverage) node));
- return IReportVisitor.NOP;
- }
-
- @Override
- protected void headExtra(final HTMLElement head) throws IOException {
- super.headExtra(head);
- head.script("text/javascript",
- context.getResources().getLink(folder, Resources.SORT_SCRIPT));
- }
-
- @Override
- protected String getOnload() {
- return "initialSort(['breadcrumb'])";
- }
-
- @Override
- protected void content(final HTMLElement body) throws IOException {
- context.getTable().render(body, methods, getNode(),
- context.getResources(), folder);
- }
-
- @Override
- protected String getFileName() {
- final String vmname = getNode().getName();
- final int pos = vmname.lastIndexOf('/');
- final String shortname = pos == -1 ? vmname : vmname.substring(pos + 1);
- return shortname + ".html";
- }
-
- @Override
- public String getLinkLabel() {
- return label;
- }
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/GroupPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/GroupPage.java
deleted file mode 100644
index d612712..0000000
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/GroupPage.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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.html;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.ISourceFileLocator;
-import org.jacoco.report.ReportOutputFolder;
-import org.jacoco.report.internal.html.resources.Resources;
-
-/**
- * Page showing coverage information for a node that groups other nodes. The
- * page shows a table of linked nodes.
- */
-public class GroupPage extends NodePage {
-
- private final List<NodePage> children = new ArrayList<NodePage>();
-
- /**
- * Creates a new visitor in the given context.
- *
- * @param node
- * @param parent
- * @param folder
- * @param context
- */
- public GroupPage(final ICoverageNode node, final ReportPage parent,
- final ReportOutputFolder folder, final IHTMLReportContext context) {
- super(node, parent, folder, context);
- }
-
- public IReportVisitor visitChild(final ICoverageNode node) {
- final NodePage child;
- switch (node.getElementType()) {
- case PACKAGE:
- child = new PackagePage(node, this, folder.subFolder(node.getName()
- .replace('/', '.')), context);
- break;
- default:
- child = new GroupPage(node, this, folder.subFolder(node.getName()),
- context);
- break;
- }
- children.add(child);
- return child;
- }
-
- @Override
- public void visitEnd(final ISourceFileLocator sourceFileLocator)
- throws IOException {
- super.visitEnd(sourceFileLocator);
- // free memory, otherwise we will keep the complete tree:
- children.clear();
- }
-
- @Override
- protected void headExtra(final HTMLElement head) throws IOException {
- super.headExtra(head);
- head.script("text/javascript",
- context.getResources().getLink(folder, Resources.SORT_SCRIPT));
- }
-
- @Override
- protected String getOnload() {
- return "initialSort(['breadcrumb', 'coveragetable'])";
- }
-
- @Override
- protected void content(final HTMLElement body) throws IOException {
- context.getTable().render(body, children, getNode(),
- context.getResources(), folder);
- }
-
- @Override
- protected String getFileName() {
- return "index.html";
- }
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLElement.java b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLElement.java
index 617e61e..e94cc3f 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLElement.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLElement.java
@@ -14,7 +14,7 @@
import java.io.IOException;
import java.io.Writer;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.xml.XMLElement;
/**
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLGroupVisitor.java b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLGroupVisitor.java
new file mode 100644
index 0000000..8d98722
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLGroupVisitor.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.html;
+
+import java.io.IOException;
+
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.analysis.ICoverageNode;
+import org.jacoco.report.ISourceFileLocator;
+import org.jacoco.report.internal.AbstractGroupVisitor;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.page.BundlePage;
+import org.jacoco.report.internal.html.page.GroupPage;
+import org.jacoco.report.internal.html.page.NodePage;
+import org.jacoco.report.internal.html.page.ReportPage;
+
+/**
+ * Group visitor for HTML reports.
+ */
+public class HTMLGroupVisitor extends AbstractGroupVisitor {
+
+ private final ReportOutputFolder folder;
+
+ private final IHTMLReportContext context;
+
+ private final GroupPage page;
+
+ /**
+ * Create a new group handler.
+ *
+ * @param parent
+ * @param folder
+ * @param context
+ * @param name
+ */
+ public HTMLGroupVisitor(final ReportPage parent,
+ final ReportOutputFolder folder, final IHTMLReportContext context,
+ final String name) {
+ super(name);
+ this.folder = folder;
+ this.context = context;
+ page = new GroupPage(total, parent, folder, context);
+ }
+
+ /**
+ * Returns the page rendered for this group.
+ *
+ * @return page for this group
+ */
+ public NodePage<ICoverageNode> getPage() {
+ return page;
+ }
+
+ @Override
+ protected void handleBundle(final IBundleCoverage bundle,
+ final ISourceFileLocator locator) throws IOException {
+ final BundlePage bundlepage = new BundlePage(bundle, page, locator,
+ folder.subFolder(bundle.getName()), context);
+ bundlepage.render();
+ page.addItem(bundlepage);
+ }
+
+ @Override
+ protected AbstractGroupVisitor handleGroup(final String name)
+ throws IOException {
+ final HTMLGroupVisitor handler = new HTMLGroupVisitor(page,
+ folder.subFolder(name), context, name);
+ page.addItem(handler.getPage());
+ return handler;
+ }
+
+ @Override
+ protected void handleEnd() throws IOException {
+ page.render();
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/ILinkable.java b/org.jacoco.report/src/org/jacoco/report/internal/html/ILinkable.java
index ebcac38..895884b 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/ILinkable.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/ILinkable.java
@@ -11,7 +11,7 @@
*******************************************************************************/
package org.jacoco.report.internal.html;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
/**
* Abstraction for items that can be linked to in a report.
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/PackagePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/PackagePage.java
index 8103c5c..107c22f 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/PackagePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/PackagePage.java
@@ -12,74 +12,77 @@
package org.jacoco.report.internal.html;
import java.io.IOException;
-import java.util.ArrayList;
+import java.io.Reader;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import org.jacoco.core.analysis.IClassCoverage;
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
+import org.jacoco.core.analysis.IPackageCoverage;
import org.jacoco.core.analysis.ISourceFileCoverage;
-import org.jacoco.report.IReportVisitor;
import org.jacoco.report.ISourceFileLocator;
-import org.jacoco.report.ReportOutputFolder;
-import org.jacoco.report.internal.html.resources.Resources;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.page.ClassPage;
+import org.jacoco.report.internal.html.page.ReportPage;
+import org.jacoco.report.internal.html.page.SourceFilePage;
+import org.jacoco.report.internal.html.page.TablePage;
/**
* Page showing coverage information for a Java package. The page contains a
* table with all classes of the package.
*/
-public class PackagePage extends NodePage {
+public class PackagePage extends TablePage<IPackageCoverage> {
- private final List<ClassPage> classes = new ArrayList<ClassPage>();
-
- private final Map<String, SourceFilePage> sourceFiles = new HashMap<String, SourceFilePage>();
+ private final ISourceFileLocator locator;
/**
* Creates a new visitor in the given context.
*
* @param node
* @param parent
+ * @param locator
* @param folder
* @param context
*/
- public PackagePage(final ICoverageNode node, final ReportPage parent,
- final ReportOutputFolder folder, final IHTMLReportContext context) {
+ public PackagePage(final IPackageCoverage node, final ReportPage parent,
+ final ISourceFileLocator locator, final ReportOutputFolder folder,
+ final IHTMLReportContext context) {
super(node, parent, folder, context);
+ this.locator = locator;
}
- public IReportVisitor visitChild(final ICoverageNode node) {
- final ElementType type = node.getElementType();
- switch (type) {
- case SOURCEFILE:
- final SourceFilePage sourcePage = new SourceFilePage(
- (ISourceFileCoverage) node, this, folder, context);
- sourceFiles.put(node.getName(), sourcePage);
- return sourcePage;
- case CLASS:
- final ClassPage classPage = new ClassPage((IClassCoverage) node,
- this, sourceFiles, folder, context);
- classes.add(classPage);
- return classPage;
+ @Override
+ public void render() throws IOException {
+ final Map<String, ILinkable> sourceFiles = renderSourceFiles();
+ renderClasses(sourceFiles);
+ super.render();
+ }
+
+ private final Map<String, ILinkable> renderSourceFiles() throws IOException {
+ final Map<String, ILinkable> sourceFiles = new HashMap<String, ILinkable>();
+ final String packagename = getNode().getName();
+ for (final ISourceFileCoverage s : getNode().getSourceFiles()) {
+ final String sourcename = s.getName();
+ final Reader reader = locator
+ .getSourceFile(packagename, sourcename);
+ if (reader != null) {
+ final SourceFilePage sourcePage = new SourceFilePage(s, reader,
+ this, folder, context);
+ sourcePage.render();
+ sourceFiles.put(sourcename, sourcePage);
+ }
+
}
- throw new AssertionError("Unexpected element type " + type);
+ return sourceFiles;
}
- @Override
- public void visitEnd(final ISourceFileLocator sourceFileLocator)
+ private void renderClasses(final Map<String, ILinkable> sourceFiles)
throws IOException {
- super.visitEnd(sourceFileLocator);
- // free memory, otherwise we will keep the complete tree:
- classes.clear();
- sourceFiles.clear();
- }
-
- @Override
- protected void headExtra(final HTMLElement head) throws IOException {
- super.headExtra(head);
- head.script("text/javascript",
- context.getResources().getLink(folder, Resources.SORT_SCRIPT));
+ for (final IClassCoverage c : getNode().getClasses()) {
+ final ClassPage page = new ClassPage(c, this, sourceFiles.get(c
+ .getSourceFileName()), folder, context);
+ page.render();
+ addItem(page);
+ }
}
@Override
@@ -88,12 +91,6 @@
}
@Override
- protected void content(final HTMLElement body) throws IOException {
- context.getTable().render(body, classes, getNode(),
- context.getResources(), folder);
- }
-
- @Override
protected String getFileName() {
return "index.html";
}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/SourceFilePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/SourceFilePage.java
deleted file mode 100644
index a07dbe7..0000000
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/SourceFilePage.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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.html;
-
-import java.io.IOException;
-import java.io.Reader;
-
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ISourceFileCoverage;
-import org.jacoco.core.analysis.ISourceNode;
-import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.ISourceFileLocator;
-import org.jacoco.report.ReportOutputFolder;
-import org.jacoco.report.internal.html.resources.Resources;
-
-/**
- * Page showing the content of a source file with numbered and highlighted
- * source lines.
- */
-public class SourceFilePage extends NodePage {
-
- private Reader sourceReader;
-
- private final String packageName;
-
- private final ISourceNode source;
-
- /**
- * Creates a new page with given information.
- *
- * @param sourceFileNode
- * @param parent
- * @param folder
- * @param context
- */
- public SourceFilePage(final ISourceFileCoverage sourceFileNode,
- final ReportPage parent, final ReportOutputFolder folder,
- final IHTMLReportContext context) {
- super(sourceFileNode, parent, folder, context);
- packageName = sourceFileNode.getPackageName();
- source = sourceFileNode;
- }
-
- public IReportVisitor visitChild(final ICoverageNode node) {
- throw new AssertionError("Source don't have child nodes.");
- }
-
- @Override
- public void visitEnd(final ISourceFileLocator sourceFileLocator)
- throws IOException {
- sourceReader = sourceFileLocator.getSourceFile(packageName, getNode()
- .getName());
- if (sourceReader != null) {
- super.visitEnd(sourceFileLocator);
- }
- }
-
- @Override
- protected void content(final HTMLElement body) throws IOException {
- final SourceHighlighter hl = new SourceHighlighter(context.getLocale());
- hl.render(body, source, sourceReader);
- sourceReader.close();
- }
-
- @Override
- protected void headExtra(final HTMLElement head) throws IOException {
- super.headExtra(head);
- head.link(
- "stylesheet",
- context.getResources().getLink(folder,
- Resources.PRETTIFY_STYLESHEET), "text/css");
- head.script(
- "text/javascript",
- context.getResources().getLink(folder,
- Resources.PRETTIFY_SCRIPT));
- }
-
- @Override
- protected String getOnload() {
- return "prettyPrint()";
- }
-
- @Override
- protected String getFileName() {
- return getNode().getName() + ".html";
- }
-
- /**
- * Checks whether this page has actually been rendered. This might not be
- * the case if no source file has been found.
- *
- * @return whether the page has been created
- */
- public boolean exists() {
- return sourceReader != null;
- }
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java b/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
index 423a45e..8d32249 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
@@ -14,7 +14,7 @@
import java.util.HashMap;
import java.util.Map;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.ILinkable;
/**
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/BundlePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/BundlePage.java
new file mode 100644
index 0000000..c21d067
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/BundlePage.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.html.page;
+
+import java.io.IOException;
+
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.analysis.IPackageCoverage;
+import org.jacoco.report.ISourceFileLocator;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.PackagePage;
+
+/**
+ * Page showing coverage information for a bundle. The page contains a table
+ * with all packages of the bundle.
+ */
+public class BundlePage extends TablePage<IBundleCoverage> {
+
+ private final ISourceFileLocator locator;
+
+ /**
+ * Creates a new visitor in the given context.
+ *
+ * @param node
+ * @param parent
+ * @param locator
+ * @param folder
+ * @param context
+ */
+ public BundlePage(final IBundleCoverage node, final ReportPage parent,
+ final ISourceFileLocator locator, final ReportOutputFolder folder,
+ final IHTMLReportContext context) {
+ super(node, parent, folder, context);
+ this.locator = locator;
+ }
+
+ @Override
+ public void render() throws IOException {
+ renderPackages();
+ super.render();
+ }
+
+ private void renderPackages() throws IOException {
+ for (final IPackageCoverage p : getNode().getPackages()) {
+ final String packagename = p.getName();
+ final String foldername = packagename.length() == 0 ? "default"
+ : packagename.replace('/', '.');
+ final PackagePage page = new PackagePage(p, this, locator,
+ folder.subFolder(foldername), context);
+ page.render();
+ addItem(page);
+ }
+ }
+
+ @Override
+ protected String getOnload() {
+ return "initialSort(['breadcrumb', 'coveragetable'])";
+ }
+
+ @Override
+ protected String getFileName() {
+ return "index.html";
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/ClassPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/ClassPage.java
new file mode 100644
index 0000000..8546b5c
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/ClassPage.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.html.page;
+
+import java.io.IOException;
+
+import org.jacoco.core.analysis.IClassCoverage;
+import org.jacoco.core.analysis.ICoverageNode;
+import org.jacoco.core.analysis.IMethodCoverage;
+import org.jacoco.core.analysis.ISourceNode;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.ILinkable;
+import org.jacoco.report.internal.html.resources.Styles;
+import org.jacoco.report.internal.html.table.ITableItem;
+
+/**
+ * Page showing coverage information for a class as a table of methods. The
+ * methods are linked to the corresponding source file.
+ */
+public class ClassPage extends TablePage<IClassCoverage> {
+
+ private class MethodItem implements ITableItem {
+
+ private final IMethodCoverage node;
+
+ MethodItem(final IMethodCoverage node) {
+ this.node = node;
+ }
+
+ public String getLinkLabel() {
+ return context.getLanguageNames().getMethodName(
+ ClassPage.this.getNode().getName(), node.getName(),
+ node.getDesc(), node.getSignature());
+ }
+
+ public String getLinkStyle() {
+ return Styles.EL_METHOD;
+ }
+
+ public String getLink(final ReportOutputFolder base) {
+ if (sourcePage == null) {
+ return null;
+ }
+ final String link = sourcePage.getLink(base);
+ final int first = node.getFirstLine();
+ return first != ISourceNode.UNKNOWN_LINE ? link + "#L" + first
+ : link;
+ }
+
+ public ICoverageNode getNode() {
+ return node;
+ }
+
+ }
+
+ private final ILinkable sourcePage;
+
+ /**
+ * Creates a new visitor in the given context.
+ *
+ * @param classNode
+ * @param parent
+ * @param sourcePage
+ * corresponding source page or <code>null</code>
+ * @param folder
+ * @param context
+ */
+ public ClassPage(final IClassCoverage classNode, final ReportPage parent,
+ final ILinkable sourcePage, final ReportOutputFolder folder,
+ final IHTMLReportContext context) {
+ super(classNode, parent, folder, context);
+ this.sourcePage = sourcePage;
+ context.getIndexUpdate().addClass(this, classNode.getId());
+ }
+
+ @Override
+ protected String getOnload() {
+ return "initialSort(['breadcrumb'])";
+ }
+
+ @Override
+ public void render() throws IOException {
+ for (final IMethodCoverage m : getNode().getMethods()) {
+ addItem(new MethodItem(m));
+ }
+ super.render();
+ }
+
+ @Override
+ protected String getFileName() {
+ final String vmname = getNode().getName();
+ final int pos = vmname.lastIndexOf('/');
+ final String shortname = pos == -1 ? vmname : vmname.substring(pos + 1);
+ return shortname + ".html";
+ }
+
+ @Override
+ public String getLinkLabel() {
+ return context.getLanguageNames().getClassName(getNode().getName(),
+ getNode().getSignature(), getNode().getSuperName(),
+ getNode().getInterfaceNames());
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/GroupPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/GroupPage.java
new file mode 100644
index 0000000..c362954
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/GroupPage.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.html.page;
+
+import org.jacoco.core.analysis.ICoverageNode;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+
+/**
+ * Page showing coverage information for a node that groups other nodes. The
+ * page shows a table of linked nodes.
+ */
+public class GroupPage extends TablePage<ICoverageNode> {
+
+ /**
+ * Creates a new visitor in the given context.
+ *
+ * @param node
+ * @param parent
+ * @param folder
+ * @param context
+ */
+ public GroupPage(final ICoverageNode node, final ReportPage parent,
+ final ReportOutputFolder folder, final IHTMLReportContext context) {
+ super(node, parent, folder, context);
+ }
+
+ @Override
+ protected String getOnload() {
+ return "initialSort(['breadcrumb', 'coveragetable'])";
+ }
+
+ @Override
+ protected String getFileName() {
+ return "index.html";
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/NodePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/NodePage.java
similarity index 70%
rename from org.jacoco.report/src/org/jacoco/report/internal/html/NodePage.java
rename to org.jacoco.report/src/org/jacoco/report/internal/html/page/NodePage.java
index e82864f..f54b07c 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/NodePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/NodePage.java
@@ -9,24 +9,24 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
-
-import java.io.IOException;
+package org.jacoco.report.internal.html.page;
import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.ISourceFileLocator;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.IHTMLReportContext;
import org.jacoco.report.internal.html.resources.Resources;
import org.jacoco.report.internal.html.table.ITableItem;
/**
* Report page that represents a coverage node.
+ *
+ * @param <NodeType>
+ * type of the node represented by this page
*/
-public abstract class NodePage extends ReportPage implements IReportVisitor,
- ITableItem {
+public abstract class NodePage<NodeType extends ICoverageNode> extends
+ ReportPage implements ITableItem {
- private ICoverageNode node;
+ private final NodeType node;
/**
* Creates a new node page.
@@ -40,29 +40,25 @@
* @param context
* settings context
*/
- protected NodePage(final ICoverageNode node, final ReportPage parent,
+ protected NodePage(final NodeType node, final ReportPage parent,
final ReportOutputFolder folder, final IHTMLReportContext context) {
super(parent, folder, context);
this.node = node;
}
+ // === ILinkable ===
+
public String getLinkStyle() {
return Resources.getElementStyle(node.getElementType());
}
- public void visitEnd(final ISourceFileLocator sourceFileLocator)
- throws IOException {
- renderDocument();
- this.node = node.getPlainCopy();
- }
-
- // === ICoverageTableItem ===
-
public String getLinkLabel() {
return node.getName();
}
- public ICoverageNode getNode() {
+ // === ICoverageTableItem ===
+
+ public NodeType getNode() {
return node;
}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/ReportPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/ReportPage.java
similarity index 90%
rename from org.jacoco.report/src/org/jacoco/report/internal/html/ReportPage.java
rename to org.jacoco.report/src/org/jacoco/report/internal/html/page/ReportPage.java
index afff57c..9cd12ca 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/ReportPage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/ReportPage.java
@@ -9,12 +9,16 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
+package org.jacoco.report.internal.html.page;
import java.io.IOException;
import org.jacoco.core.JaCoCo;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLDocument;
+import org.jacoco.report.internal.html.HTMLElement;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.ILinkable;
import org.jacoco.report.internal.html.resources.Resources;
import org.jacoco.report.internal.html.resources.Styles;
@@ -51,11 +55,12 @@
}
/**
- * Renders the page content. This method must be called at most once.
+ * Renders this page's content and optionally additional pages. This method
+ * must be called at most once.
*
* @throws IOException
*/
- public final void renderDocument() throws IOException {
+ public void render() throws IOException {
final HTMLDocument doc = new HTMLDocument(
folder.createFile(getFileName()), context.getOutputEncoding());
head(doc.head());
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/SessionsPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
similarity index 95%
rename from org.jacoco.report/src/org/jacoco/report/internal/html/SessionsPage.java
rename to org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
index ca3cca5..434d255 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/SessionsPage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
@@ -9,7 +9,7 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
+package org.jacoco.report.internal.html.page;
import java.io.IOException;
import java.text.DateFormat;
@@ -23,7 +23,9 @@
import org.jacoco.core.data.ExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.ILanguageNames;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLElement;
+import org.jacoco.report.internal.html.IHTMLReportContext;
import org.jacoco.report.internal.html.index.ElementIndex;
import org.jacoco.report.internal.html.resources.Styles;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFilePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFilePage.java
new file mode 100644
index 0000000..5c4e7be
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFilePage.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.html.page;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.jacoco.core.analysis.ISourceFileCoverage;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLElement;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.resources.Resources;
+
+/**
+ * Page showing the content of a source file with numbered and highlighted
+ * source lines.
+ */
+public class SourceFilePage extends NodePage<ISourceFileCoverage> {
+
+ private final Reader sourceReader;
+
+ /**
+ * Creates a new page with given information.
+ *
+ * @param sourceFileNode
+ * @param sourceReader
+ * @param parent
+ * @param folder
+ * @param context
+ */
+ public SourceFilePage(final ISourceFileCoverage sourceFileNode,
+ final Reader sourceReader, final ReportPage parent,
+ final ReportOutputFolder folder, final IHTMLReportContext context) {
+ super(sourceFileNode, parent, folder, context);
+ this.sourceReader = sourceReader;
+ }
+
+ @Override
+ protected void content(final HTMLElement body) throws IOException {
+ final SourceHighlighter hl = new SourceHighlighter(context.getLocale());
+ hl.render(body, getNode(), sourceReader);
+ sourceReader.close();
+ }
+
+ @Override
+ protected void headExtra(final HTMLElement head) throws IOException {
+ super.headExtra(head);
+ head.link(
+ "stylesheet",
+ context.getResources().getLink(folder,
+ Resources.PRETTIFY_STYLESHEET), "text/css");
+ head.script(
+ "text/javascript",
+ context.getResources().getLink(folder,
+ Resources.PRETTIFY_SCRIPT));
+ }
+
+ @Override
+ protected String getOnload() {
+ return "prettyPrint()";
+ }
+
+ @Override
+ protected String getFileName() {
+ return getNode().getName() + ".html";
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/SourceHighlighter.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceHighlighter.java
similarity index 97%
rename from org.jacoco.report/src/org/jacoco/report/internal/html/SourceHighlighter.java
rename to org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceHighlighter.java
index 7002b7e..49a9942 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/SourceHighlighter.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceHighlighter.java
@@ -9,7 +9,7 @@
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
-package org.jacoco.report.internal.html;
+package org.jacoco.report.internal.html.page;
import java.io.BufferedReader;
import java.io.IOException;
@@ -20,6 +20,7 @@
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.ILine;
import org.jacoco.core.analysis.ISourceNode;
+import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.resources.Styles;
/**
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/TablePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/TablePage.java
new file mode 100644
index 0000000..5437a91
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/TablePage.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.html.page;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jacoco.core.analysis.ICoverageNode;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLElement;
+import org.jacoco.report.internal.html.IHTMLReportContext;
+import org.jacoco.report.internal.html.resources.Resources;
+import org.jacoco.report.internal.html.table.ITableItem;
+
+/**
+ * Report page that contains a table of items linked to other pages.
+ *
+ * @param <NodeType>
+ * type of the node represented by this page
+ */
+public abstract class TablePage<NodeType extends ICoverageNode> extends
+ NodePage<NodeType> implements ITableItem {
+
+ private final List<ITableItem> items = new ArrayList<ITableItem>();
+
+ /**
+ * Creates a new node page.
+ *
+ * @param node
+ * corresponding node
+ * @param parent
+ * optional hierarchical parent
+ * @param folder
+ * base folder to create this report in
+ * @param context
+ * settings context
+ */
+ protected TablePage(final NodeType node, final ReportPage parent,
+ final ReportOutputFolder folder, final IHTMLReportContext context) {
+ super(node, parent, folder, context);
+ }
+
+ /**
+ * Adds the given item to the table. Method must be called before the page
+ * is rendered.
+ *
+ * @param item
+ */
+ public void addItem(final ITableItem item) {
+ items.add(item);
+ }
+
+ @Override
+ protected void headExtra(final HTMLElement head) throws IOException {
+ super.headExtra(head);
+ head.script("text/javascript",
+ context.getResources().getLink(folder, Resources.SORT_SCRIPT));
+ }
+
+ @Override
+ protected void content(final HTMLElement body) throws IOException {
+ context.getTable().render(body, items, getNode(),
+ context.getResources(), folder);
+ // free memory, otherwise we will keep the complete page tree:
+ items.clear();
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Resources.java b/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Resources.java
index 1ffc3e0..750d7d8 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Resources.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Resources.java
@@ -16,7 +16,7 @@
import java.io.OutputStream;
import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
/**
* Static resource that are included with the coverage report and might be
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/BarColumn.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/BarColumn.java
index 18747cb..60f5b98 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/BarColumn.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/BarColumn.java
@@ -22,7 +22,7 @@
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.ICoverageNode;
import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.resources.Resources;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/CounterColumn.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/CounterColumn.java
index fdd04b0..ea73b95 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/CounterColumn.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/CounterColumn.java
@@ -22,7 +22,7 @@
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.ICoverageNode;
import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.resources.Resources;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/IColumnRenderer.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/IColumnRenderer.java
index 80fb95c..c251f8e 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/IColumnRenderer.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/IColumnRenderer.java
@@ -16,7 +16,7 @@
import java.util.List;
import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.resources.Resources;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/LabelColumn.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/LabelColumn.java
index 92ba6d0..fc2d019 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/LabelColumn.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/LabelColumn.java
@@ -16,7 +16,7 @@
import java.util.List;
import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.resources.Resources;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/PercentageColumn.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/PercentageColumn.java
index c1166e4..148cc56 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/PercentageColumn.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/PercentageColumn.java
@@ -22,7 +22,7 @@
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.ICoverageNode;
import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.resources.Resources;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/Table.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/Table.java
index 2d3ba12..606a3ce 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/Table.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/Table.java
@@ -18,7 +18,7 @@
import java.util.List;
import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.report.ReportOutputFolder;
+import org.jacoco.report.internal.ReportOutputFolder;
import org.jacoco.report.internal.html.HTMLElement;
import org.jacoco.report.internal.html.resources.Resources;
import org.jacoco.report.internal.html.resources.Styles;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLCoverageWriter.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLCoverageWriter.java
new file mode 100644
index 0000000..76ad64f
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLCoverageWriter.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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 org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.analysis.IClassCoverage;
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.analysis.ICoverageNode;
+import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
+import org.jacoco.core.analysis.ILine;
+import org.jacoco.core.analysis.IMethodCoverage;
+import org.jacoco.core.analysis.IPackageCoverage;
+import org.jacoco.core.analysis.ISourceFileCoverage;
+import org.jacoco.core.analysis.ISourceNode;
+
+/**
+ * Serializes coverage data as XML fragments.
+ */
+public class XMLCoverageWriter {
+
+ /**
+ * Creates a child element with a name attribute.
+ *
+ * @param parent
+ * parent element
+ * @param tagname
+ * name of the child tag
+ * @param name
+ * value of the name attribute
+ * @return child element
+ * @throws IOException
+ */
+ public static XMLElement createChild(final XMLElement parent,
+ final String tagname, final String name) throws IOException {
+ final XMLElement child = parent.element(tagname);
+ child.attr("name", name);
+ return child;
+ }
+
+ /**
+ * Writes the structure of a given bundle.
+ *
+ * @param bundle
+ * bundle coverage data
+ * @param element
+ * container element for the bundle data
+ * @throws IOException
+ */
+ public static void writeBundle(final IBundleCoverage bundle,
+ final XMLElement element) throws IOException {
+ for (final IPackageCoverage p : bundle.getPackages()) {
+ writePackage(p, element);
+ }
+ writeCounters(bundle, element);
+ }
+
+ private static void writePackage(final IPackageCoverage p,
+ final XMLElement parent) throws IOException {
+ final XMLElement element = createChild(parent, "package", p.getName());
+ for (final IClassCoverage c : p.getClasses()) {
+ writeClass(c, element);
+ }
+ for (final ISourceFileCoverage s : p.getSourceFiles()) {
+ writeSourceFile(s, element);
+ }
+ writeCounters(p, element);
+ }
+
+ private static void writeClass(final IClassCoverage c,
+ final XMLElement parent) throws IOException {
+ final XMLElement element = createChild(parent, "class", c.getName());
+ for (final IMethodCoverage m : c.getMethods()) {
+ writeMethod(m, element);
+ }
+ writeCounters(c, element);
+ }
+
+ private static void writeMethod(final IMethodCoverage m,
+ final XMLElement parent) throws IOException {
+ final XMLElement element = createChild(parent, "method", m.getName());
+ element.attr("desc", m.getDesc());
+ final int line = m.getFirstLine();
+ if (line != -1) {
+ element.attr("line", line);
+ }
+ writeCounters(m, element);
+ }
+
+ private static void writeSourceFile(final ISourceFileCoverage s,
+ final XMLElement parent) throws IOException {
+ final XMLElement element = createChild(parent, "sourcefile",
+ s.getName());
+ writeLines(s, element);
+ writeCounters(s, element);
+ }
+
+ /**
+ * Writes all non-zero counters of the given node.
+ *
+ * @param node
+ * node to retrieve counters from
+ * @param parent
+ * container for the counter elements
+ * @throws IOException
+ */
+ public static void writeCounters(final ICoverageNode node,
+ final XMLElement parent) throws IOException {
+ for (final CounterEntity counterEntity : CounterEntity.values()) {
+ final ICounter counter = node.getCounter(counterEntity);
+ if (counter.getTotalCount() > 0) {
+ final XMLElement counterNode = parent.element("counter");
+ counterNode.attr("type", counterEntity.name());
+ writeCounter(counterNode, "missed", "covered", counter);
+ counterNode.close();
+ }
+ }
+ }
+
+ private static void writeLines(final ISourceNode source,
+ final XMLElement parent) throws IOException {
+ final int last = source.getLastLine();
+ for (int nr = source.getFirstLine(); nr <= last; nr++) {
+ final ILine line = source.getLine(nr);
+ if (line.getStatus() != ICounter.EMPTY) {
+ final XMLElement element = parent.element("line");
+ element.attr("nr", nr);
+ writeCounter(element, "mi", "ci", line.getInstructionCounter());
+ writeCounter(element, "mb", "cb", line.getBranchCounter());
+ }
+ }
+ }
+
+ private static void writeCounter(final XMLElement element,
+ final String missedattr, final String coveredattr,
+ final ICounter counter) throws IOException {
+ element.attr(missedattr, counter.getMissedCount());
+ element.attr(coveredattr, counter.getCoveredCount());
+ }
+
+ private XMLCoverageWriter() {
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLGroupVisitor.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLGroupVisitor.java
new file mode 100644
index 0000000..5cbba87
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLGroupVisitor.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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:
+ * Brock Janiczak - initial API and implementation
+ * Marc R. Hoffmann - generalized structure, line info
+ *
+ *******************************************************************************/
+package org.jacoco.report.internal.xml;
+
+import java.io.IOException;
+
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.report.IReportGroupVisitor;
+import org.jacoco.report.ISourceFileLocator;
+import org.jacoco.report.internal.AbstractGroupVisitor;
+
+/**
+ * {@link IReportGroupVisitor} that transforms the report structure into XML
+ * elements.
+ */
+public class XMLGroupVisitor extends AbstractGroupVisitor {
+
+ /** XML element of this group */
+ protected final XMLElement element;
+
+ /**
+ * New handler for a group with the given name.
+ *
+ * @param element
+ * XML-Element representing this coverage node. The start tag
+ * must not be closed yet to allow adding additional attributes.
+ * @param name
+ * name of the group
+ * @throws IOException
+ * in case of problems with the underlying writer
+ */
+ public XMLGroupVisitor(final XMLElement element, final String name)
+ throws IOException {
+ super(name);
+ this.element = element;
+ }
+
+ @Override
+ protected void handleBundle(final IBundleCoverage bundle,
+ final ISourceFileLocator locator) throws IOException {
+ final XMLElement child = createChild(bundle.getName());
+ XMLCoverageWriter.writeBundle(bundle, child);
+ }
+
+ @Override
+ protected AbstractGroupVisitor handleGroup(final String name)
+ throws IOException {
+ final XMLElement child = createChild(name);
+ return new XMLGroupVisitor(child, name);
+ }
+
+ @Override
+ protected void handleEnd() throws IOException {
+ XMLCoverageWriter.writeCounters(total, element);
+ }
+
+ private XMLElement createChild(final String name) throws IOException {
+ return XMLCoverageWriter.createChild(element, "group", name);
+ }
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLReportNodeHandler.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLReportNodeHandler.java
deleted file mode 100644
index 002fdb2..0000000
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLReportNodeHandler.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2011 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:
- * Brock Janiczak - initial API and implementation
- * Marc R. Hoffmann - generalized structure, line info
- *
- *******************************************************************************/
-package org.jacoco.report.internal.xml;
-
-import java.io.IOException;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.analysis.ICoverageNode;
-import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
-import org.jacoco.core.analysis.ICoverageNode.ElementType;
-import org.jacoco.core.analysis.ILine;
-import org.jacoco.core.analysis.IMethodCoverage;
-import org.jacoco.core.analysis.ISourceNode;
-import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.ISourceFileLocator;
-
-/**
- * Report visitor that transforms the report structure into XML elements.
- */
-public class XMLReportNodeHandler implements IReportVisitor {
-
- private final XMLElement element;
-
- private final ICoverageNode node;
-
- /**
- * New handler for the given coverage node.
- *
- * @param element
- * XML-Element representing this coverage node. The start tag
- * must not be closed yet to allow adding additional attributes.
- * @param node
- * corresponding coverage node
- * @throws IOException
- * in case of problems with the underlying writer
- */
- public XMLReportNodeHandler(final XMLElement element,
- final ICoverageNode node) throws IOException {
- this.element = element;
- this.node = node;
- element.attr("name", node.getName());
- insertElementsBefore(element);
- }
-
- /**
- * Hook to add XML elements before the child elements created by default.
- *
- * @param element
- * this element
- * @throws IOException
- */
- protected void insertElementsBefore(final XMLElement element)
- throws IOException {
- }
-
- /**
- * Hook to add XML elements before the child elements created by default.
- *
- * @param element
- * this element
- * @throws IOException
- */
- void insertElementsAfter(final XMLElement element) throws IOException {
- }
-
- public IReportVisitor visitChild(final ICoverageNode node)
- throws IOException {
- final ElementType type = node.getElementType();
- switch (type) {
- case GROUP:
- case BUNDLE:
- return new XMLReportNodeHandler(element.element("group"), node);
- case PACKAGE:
- return new XMLReportNodeHandler(element.element("package"), node);
- case CLASS:
- return new XMLReportNodeHandler(element.element("class"), node);
- case METHOD:
- final XMLElement methodChild = element.element("method");
- final IMethodCoverage methodNode = (IMethodCoverage) node;
- methodChild.attr("desc", methodNode.getDesc());
- final int line = methodNode.getFirstLine();
- if (line != -1) {
- methodChild.attr("line", line);
- }
- return new XMLReportNodeHandler(methodChild, node);
- case SOURCEFILE:
- return new XMLReportNodeHandler(element.element("sourcefile"), node) {
- @Override
- protected void insertElementsAfter(final XMLElement element)
- throws IOException {
- writeLines((ISourceNode) node, element);
- }
- };
- default:
- throw new AssertionError(type);
- }
- }
-
- public final void visitEnd(final ISourceFileLocator sourceFileLocator)
- throws IOException {
- insertElementsAfter(element);
- for (final CounterEntity counterEntity : CounterEntity.values()) {
- createCounterElement(counterEntity);
- }
- element.close();
- }
-
- private void createCounterElement(final CounterEntity counterEntity)
- throws IOException {
- final ICounter counter = node.getCounter(counterEntity);
- if (counter.getTotalCount() > 0) {
- final XMLElement counterNode = this.element.element("counter");
- counterNode.attr("type", counterEntity.name());
- counterNode.attr("covered", counter.getCoveredCount());
- counterNode.attr("missed", counter.getMissedCount());
- counterNode.close();
- }
- }
-
- private static void writeLines(final ISourceNode source,
- final XMLElement parent) throws IOException {
- final int last = source.getLastLine();
- for (int nr = source.getFirstLine(); nr <= last; nr++) {
- final ILine line = source.getLine(nr);
- if (line.getStatus() != ICounter.EMPTY) {
- final XMLElement element = parent.element("line");
- element.attr("nr", nr);
- final ICounter insn = line.getInstructionCounter();
- element.attr("mi", insn.getMissedCount());
- element.attr("ci", insn.getCoveredCount());
- final ICounter branches = line.getBranchCounter();
- element.attr("mb", branches.getMissedCount());
- element.attr("cb", branches.getCoveredCount());
- }
- }
- }
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java b/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
index 64e7fc1..be51a73 100644
--- a/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
@@ -12,71 +12,32 @@
package org.jacoco.report.xml;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.Collection;
import java.util.List;
-import org.jacoco.core.analysis.ICoverageNode;
+import org.jacoco.core.analysis.IBundleCoverage;
import org.jacoco.core.data.ExecutionData;
import org.jacoco.core.data.SessionInfo;
-import org.jacoco.report.IReportFormatter;
import org.jacoco.report.IReportVisitor;
-import org.jacoco.report.ISingleReportOutput;
+import org.jacoco.report.ISourceFileLocator;
+import org.jacoco.report.internal.AbstractGroupVisitor;
+import org.jacoco.report.internal.xml.XMLCoverageWriter;
import org.jacoco.report.internal.xml.XMLDocument;
import org.jacoco.report.internal.xml.XMLElement;
-import org.jacoco.report.internal.xml.XMLReportNodeHandler;
+import org.jacoco.report.internal.xml.XMLGroupVisitor;
/**
* Report formatter that creates a single XML file for a coverage session
*/
-public class XMLFormatter implements IReportFormatter {
+public class XMLFormatter {
private static final String PUBID = "-//JACOCO//DTD Report 1.0//EN";
private static final String SYSTEM = "report.dtd";
- private ISingleReportOutput output;
-
private String outputEncoding = "UTF-8";
- public IReportVisitor createReportVisitor(final ICoverageNode rootNode,
- final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData) throws IOException {
-
- if (output == null) {
- throw new IllegalStateException("No report output set.");
- }
- final XMLElement root = new XMLDocument("report", PUBID, SYSTEM,
- outputEncoding, true, output.createFile());
- return new XMLReportNodeHandler(root, rootNode) {
- @Override
- protected void insertElementsBefore(final XMLElement element)
- throws IOException {
- writeSessionInfos(element, sessionInfos);
- }
- };
- }
-
- private void writeSessionInfos(final XMLElement root,
- final List<SessionInfo> infos) throws IOException {
- for (final SessionInfo i : infos) {
- final XMLElement sessioninfo = root.element("sessioninfo");
- sessioninfo.attr("id", i.getId());
- sessioninfo.attr("start", i.getStartTimeStamp());
- sessioninfo.attr("dump", i.getDumpTimeStamp());
- }
- }
-
- /**
- * Sets the report output callback for this report formatter. This is a
- * mandatory property.
- *
- * @param output
- * report output
- */
- public void setReportOutput(final ISingleReportOutput output) {
- this.output = output;
- }
-
/**
* Sets the encoding used for generated XML document. Default is UTF-8.
*
@@ -87,4 +48,64 @@
this.outputEncoding = outputEncoding;
}
+ /**
+ * Creates a new visitor to write a report to the given stream.
+ *
+ * @param output
+ * output stream 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 OutputStream output)
+ throws IOException {
+ final XMLElement root = new XMLDocument("report", PUBID, SYSTEM,
+ outputEncoding, true, output);
+ class RootVisitor extends XMLGroupVisitor implements IReportVisitor {
+
+ RootVisitor(final XMLElement element) throws IOException {
+ super(element, null);
+ }
+
+ private List<SessionInfo> sessionInfos;
+
+ public void visitInfo(final List<SessionInfo> sessionInfos,
+ final Collection<ExecutionData> executionData)
+ throws IOException {
+ this.sessionInfos = sessionInfos;
+ }
+
+ @Override
+ protected void handleBundle(final IBundleCoverage bundle,
+ final ISourceFileLocator locator) throws IOException {
+ writeHeader(bundle.getName());
+ XMLCoverageWriter.writeBundle(bundle, element);
+ }
+
+ @Override
+ protected AbstractGroupVisitor handleGroup(final String name)
+ throws IOException {
+ writeHeader(name);
+ return new XMLGroupVisitor(element, name);
+ }
+
+ private void writeHeader(final String name) throws IOException {
+ element.attr("name", name);
+ for (final SessionInfo i : sessionInfos) {
+ final XMLElement sessioninfo = root.element("sessioninfo");
+ sessioninfo.attr("id", i.getId());
+ sessioninfo.attr("start", i.getStartTimeStamp());
+ sessioninfo.attr("dump", i.getDumpTimeStamp());
+ }
+ }
+
+ @Override
+ protected void handleEnd() throws IOException {
+ super.handleEnd();
+ element.close();
+ }
+ }
+ return new RootVisitor(root);
+ }
+
}