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