• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors
3  * This program and the accompanying materials are made available under
4  * the terms of the Eclipse Public License 2.0 which is available at
5  * http://www.eclipse.org/legal/epl-2.0
6  *
7  * SPDX-License-Identifier: EPL-2.0
8  *
9  * Contributors:
10  *    Marc R. Hoffmann - initial API and implementation
11  *
12  *******************************************************************************/
13 package org.jacoco.core.analysis;
14 
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Map;
20 
21 import org.jacoco.core.internal.analysis.BundleCoverageImpl;
22 import org.jacoco.core.internal.analysis.SourceFileCoverageImpl;
23 
24 /**
25  * Builder for hierarchical {@link ICoverageNode} structures from single
26  * {@link IClassCoverage} nodes. The nodes are feed into the builder through its
27  * {@link ICoverageVisitor} interface. Afterwards the aggregated data can be
28  * obtained with {@link #getClasses()}, {@link #getSourceFiles()} or
29  * {@link #getBundle(String)} in the following hierarchy:
30  *
31  * <pre>
32  * {@link IBundleCoverage}
33  * +-- {@link IPackageCoverage}*
34  *     +-- {@link IClassCoverage}*
35  *     +-- {@link ISourceFileCoverage}*
36  * </pre>
37  */
38 public class CoverageBuilder implements ICoverageVisitor {
39 
40 	private final Map<String, IClassCoverage> classes;
41 
42 	private final Map<String, ISourceFileCoverage> sourcefiles;
43 
44 	/**
45 	 * Create a new builder.
46 	 *
47 	 */
CoverageBuilder()48 	public CoverageBuilder() {
49 		this.classes = new HashMap<String, IClassCoverage>();
50 		this.sourcefiles = new HashMap<String, ISourceFileCoverage>();
51 	}
52 
53 	/**
54 	 * Returns all class nodes currently contained in this builder.
55 	 *
56 	 * @return all class nodes
57 	 */
getClasses()58 	public Collection<IClassCoverage> getClasses() {
59 		return Collections.unmodifiableCollection(classes.values());
60 	}
61 
62 	/**
63 	 * Returns all source file nodes currently contained in this builder.
64 	 *
65 	 * @return all source file nodes
66 	 */
getSourceFiles()67 	public Collection<ISourceFileCoverage> getSourceFiles() {
68 		return Collections.unmodifiableCollection(sourcefiles.values());
69 	}
70 
71 	/**
72 	 * Creates a bundle from all nodes currently contained in this bundle.
73 	 *
74 	 * @param name
75 	 *            Name of the bundle
76 	 * @return bundle containing all classes and source files
77 	 */
getBundle(final String name)78 	public IBundleCoverage getBundle(final String name) {
79 		return new BundleCoverageImpl(name, classes.values(),
80 				sourcefiles.values());
81 	}
82 
83 	/**
84 	 * Returns all classes for which execution data does not match.
85 	 *
86 	 * @see IClassCoverage#isNoMatch()
87 	 * @return collection of classes with non-matching execution data
88 	 */
getNoMatchClasses()89 	public Collection<IClassCoverage> getNoMatchClasses() {
90 		final Collection<IClassCoverage> result = new ArrayList<IClassCoverage>();
91 		for (final IClassCoverage c : classes.values()) {
92 			if (c.isNoMatch()) {
93 				result.add(c);
94 			}
95 		}
96 		return result;
97 	}
98 
99 	// === ICoverageVisitor ===
100 
visitCoverage(final IClassCoverage coverage)101 	public void visitCoverage(final IClassCoverage coverage) {
102 		final String name = coverage.getName();
103 		final IClassCoverage dup = classes.put(name, coverage);
104 		if (dup != null) {
105 			if (dup.getId() != coverage.getId()) {
106 				throw new IllegalStateException(
107 						"Can't add different class with same name: " + name);
108 			}
109 		} else {
110 			final String source = coverage.getSourceFileName();
111 			if (source != null) {
112 				final SourceFileCoverageImpl sourceFile = getSourceFile(source,
113 						coverage.getPackageName());
114 				sourceFile.increment(coverage);
115 			}
116 		}
117 	}
118 
getSourceFile(final String filename, final String packagename)119 	private SourceFileCoverageImpl getSourceFile(final String filename,
120 			final String packagename) {
121 		final String key = packagename + '/' + filename;
122 		SourceFileCoverageImpl sourcefile = (SourceFileCoverageImpl) sourcefiles
123 				.get(key);
124 		if (sourcefile == null) {
125 			sourcefile = new SourceFileCoverageImpl(filename, packagename);
126 			sourcefiles.put(key, sourcefile);
127 		}
128 		return sourcefile;
129 	}
130 
131 }
132