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 boolean[] covered = executionData.getData(id);
90 final Collection<MethodCoverage> methods = new ArrayList<MethodCoverage>();
91 final String[] sourcename = new String[1];
92 return new IClassStructureVisitor() {
93 String name;
94 String signature;
95 String superName;
96 String[] interfaces;
97
98 public void visit(final String name, final String signature,
99 final String superName, final String[] interfaces) {
100 this.name = name;
101 this.signature = signature;
102 this.superName = superName;
103 this.interfaces = interfaces;
104 }
105
106 public void visitSourceFile(final String name) {
107 sourcename[0] = name;
108 }
109
110 public IMethodStructureVisitor visitMethodStructure(
111 final String name, final String desc, final String signature) {
112 return createMethodVisitor(name, desc, signature, methods,
113 covered);
114 }
115
116 public void visitEnd() {
117 final ClassCoverage classData = new ClassCoverage(name,
118 signature, superName, interfaces, sourcename[0],
119 methods);
120 classes.put(Long.valueOf(id), classData);
121 if (sourcename[0] != null) {
122 final SourceFileCoverage sourceFile = getSourceFile(
123 sourcename[0], classData.getPackageName());
124 sourceFile.increment(classData);
125 }
126 }
127 };
128 }
129
130 private IMethodStructureVisitor createMethodVisitor(final String name,
131 final String desc, final String signature,
132 final Collection<MethodCoverage> container, final boolean[] covered) {
133 final MethodCoverage method = new MethodCoverage(name, desc, signature);
134 return new IMethodStructureVisitor() {
135 public void block(final int id, final int instructions,
136 final int[] lineNumbers) {
137 final boolean c = covered == null ? false : covered[id];
138 method.addBlock(instructions, lineNumbers, c);
139 }
140
141 public void visitEnd() {
142 container.add(method);
143 }
144 };
145 }
146
147 private SourceFileCoverage getSourceFile(final String filename,
148 final String packagename) {
149 final String key = packagename + '/' + filename;
150 SourceFileCoverage sourcefile = sourcefiles.get(key);
151 if (sourcefile == null) {
152 sourcefile = new SourceFileCoverage(filename, packagename);
153 sourcefiles.put(key, sourcefile);
154 }
155 return sourcefile;
156 }
157
158}