CoverageBuilder.java
1/*******************************************************************************
2 * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others
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 * $Id: $
12 *******************************************************************************/
13package org.jacoco.core.analysis;
14
15import java.util.ArrayList;
16import java.util.Collection;
17import java.util.Collections;
18import java.util.HashMap;
19import java.util.Map;
20
21import org.jacoco.core.data.ExecutionDataStore;
22import org.jacoco.core.data.IClassStructureVisitor;
23import org.jacoco.core.data.IMethodStructureVisitor;
24import org.jacoco.core.data.IStructureVisitor;
25
26/**
27 * Builder for hierarchical {@link ICoverageNode} structures based on execution
28 * and structure information. The builder is constructed for a given
29 * {@link ExecutionDataStore} and then feed with class structure information
30 * through its {@link IStructureVisitor} interface. Afterwards the collected
31 * data can be obtained with {@link #getClasses()}, {@link #getSourceFiles()} or
32 * {@link #getBundle(String)}.
33 *
34 * @author Marc R. Hoffmann
35 * @version $Revision: $
36 */
37public class CoverageBuilder implements IStructureVisitor {
38
39 private final ExecutionDataStore executionData;
40
41 private final Map<Long, ClassCoverage> classes;
42
43 private final Map<String, SourceFileCoverage> sourcefiles;
44
45 /**
46 * Create a new builder based on the given execution data.
47 *
48 * @param executionData
49 * execution data
50 */
51 public CoverageBuilder(final ExecutionDataStore executionData) {
52 this.executionData = executionData;
53 this.classes = new HashMap<Long, ClassCoverage>();
54 this.sourcefiles = new HashMap<String, SourceFileCoverage>();
55 }
56
57 /**
58 * Returns all class nodes currently contained in this builder.
59 *
60 * @return all class nodes
61 */
62 public Collection<ClassCoverage> getClasses() {
63 return Collections.unmodifiableCollection(classes.values());
64 }
65
66 /**
67 * Returns all source file nodes currently contained in this builder.
68 *
69 * @return all source file nodes
70 */
71 public Collection<SourceFileCoverage> getSourceFiles() {
72 return Collections.unmodifiableCollection(sourcefiles.values());
73 }
74
75 /**
76 * Creates a bundle from all nodes currently contained in this bundle.
77 *
78 * @param name
79 * Name of the bundle
80 * @return bundle containing all classes and source files
81 */
82 public BundleCoverage getBundle(final String name) {
83 return new BundleCoverage(name, classes.values(), sourcefiles.values());
84 }
85
86 // === IStructureVisitor ===
87
88 public IClassStructureVisitor visitClassStructure(final long id,
89 final String name) {
90 final boolean[][] covered = executionData.getData(id);
91 final Collection<MethodCoverage> methods = new ArrayList<MethodCoverage>();
92 final String[] sourcename = new String[1];
93 return new IClassStructureVisitor() {
94 public void visitSourceFile(final String name) {
95 sourcename[0] = name;
96 }
97
98 public IMethodStructureVisitor visitMethodStructure(final int id,
99 final String name, final String desc, final String signature) {
100 final boolean[] c = covered == null ? null : covered[id];
101 return createMethodVisitor(name, desc, signature, methods, c);
102 }
103
104 public void visitEnd() {
105 final ClassCoverage classData = new ClassCoverage(name,
106 sourcename[0], methods);
107 classes.put(Long.valueOf(id), classData);
108 if (sourcename[0] != null) {
109 final SourceFileCoverage sourceFile = getSourceFile(
110 sourcename[0], classData.getPackageName());
111 sourceFile.increment(classData);
112 }
113 }
114 };
115 }
116
117 private IMethodStructureVisitor createMethodVisitor(final String name,
118 final String desc, final String signature,
119 final Collection<MethodCoverage> container, final boolean[] covered) {
120 final MethodCoverage method = new MethodCoverage(name, desc, signature);
121 return new IMethodStructureVisitor() {
122 public void block(final int id, final int instructions,
123 final int[] lineNumbers) {
124 final boolean c = covered == null ? false : covered[id];
125 method.addBlock(instructions, lineNumbers, c);
126 }
127
128 public void visitEnd() {
129 container.add(method);
130 }
131 };
132 }
133
134 private SourceFileCoverage getSourceFile(final String filename,
135 final String packagename) {
136 final String key = packagename + '/' + filename;
137 SourceFileCoverage sourcefile = sourcefiles.get(key);
138 if (sourcefile == null) {
139 sourcefile = new SourceFileCoverage(filename, packagename);
140 sourcefiles.put(key, sourcefile);
141 }
142 return sourcefile;
143 }
144
145}