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