CoverageBuilder.java revision 456cb13baa8f60eef812864ed5bbe3c5f858cdbb
1/*******************************************************************************
2 * Copyright (c) 2009, 2011 Mountainminds GmbH & Co. KG and Contributors
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *    Marc R. Hoffmann - initial API and implementation
10 *
11 *******************************************************************************/
12package org.jacoco.core.analysis;
13
14import java.util.Collection;
15import java.util.Collections;
16import java.util.HashMap;
17import java.util.Map;
18
19import org.jacoco.core.internal.analysis.BundleCoverageImpl;
20import org.jacoco.core.internal.analysis.SourceFileCoverageImpl;
21
22/**
23 * Builder for hierarchical {@link ICoverageNode} structures from single
24 * {@link IClassCoverage} nodes. The nodes are feed into the builder through its
25 * {@link ICoverageVisitor} interface. Afterwards the aggregated data can be
26 * obtained with {@link #getClasses()}, {@link #getSourceFiles()} or
27 * {@link #getBundle(String)} in the following hierarchy:
28 *
29 * <pre>
30 * {@link IBundleCoverage}
31 * +-- {@link IPackageCoverage}*
32 *     +-- {@link IClassCoverage}*
33 *     +-- {@link ISourceFileCoverage}*
34 * </pre>
35 */
36public class CoverageBuilder implements ICoverageVisitor {
37
38	private final Map<String, IClassCoverage> classes;
39
40	private final Map<String, ISourceFileCoverage> sourcefiles;
41
42	/**
43	 * Create a new builder.
44	 *
45	 */
46	public CoverageBuilder() {
47		this.classes = new HashMap<String, IClassCoverage>();
48		this.sourcefiles = new HashMap<String, ISourceFileCoverage>();
49	}
50
51	/**
52	 * Returns all class nodes currently contained in this builder.
53	 *
54	 * @return all class nodes
55	 */
56	public Collection<IClassCoverage> getClasses() {
57		return Collections.unmodifiableCollection(classes.values());
58	}
59
60	/**
61	 * Returns all source file nodes currently contained in this builder.
62	 *
63	 * @return all source file nodes
64	 */
65	public Collection<ISourceFileCoverage> getSourceFiles() {
66		return Collections.unmodifiableCollection(sourcefiles.values());
67	}
68
69	/**
70	 * Creates a bundle from all nodes currently contained in this bundle.
71	 *
72	 * @param name
73	 *            Name of the bundle
74	 * @return bundle containing all classes and source files
75	 */
76	public BundleCoverageImpl getBundle(final String name) {
77		return new BundleCoverageImpl(name, classes.values(),
78				sourcefiles.values());
79	}
80
81	// === IStructureVisitor ===
82
83	public void visitCoverage(final IClassCoverage coverage) {
84		// Only consider classes that actually contain code:
85		if (coverage.getInstructionCounter().getTotalCount() > 0) {
86			final String name = coverage.getName();
87			if (classes.put(name, coverage) != null) {
88				throw new IllegalStateException(
89						"Duplicate class name in same group: " + name);
90			}
91			final String source = coverage.getSourceFileName();
92			if (source != null) {
93				final SourceFileCoverageImpl sourceFile = getSourceFile(source,
94						coverage.getPackageName());
95				sourceFile.increment(coverage);
96			}
97		}
98	}
99
100	private SourceFileCoverageImpl getSourceFile(final String filename,
101			final String packagename) {
102		final String key = packagename + '/' + filename;
103		SourceFileCoverageImpl sourcefile = (SourceFileCoverageImpl) sourcefiles
104				.get(key);
105		if (sourcefile == null) {
106			sourcefile = new SourceFileCoverageImpl(filename, packagename);
107			sourcefiles.put(key, sourcefile);
108		}
109		return sourcefile;
110	}
111
112}
113