ExecutionDataStore.java
1/*******************************************************************************
2 * Copyright (c) 2009, 2010 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 *******************************************************************************/
12package org.jacoco.core.data;
13
14import java.util.Collection;
15import java.util.HashMap;
16import java.util.Map;
17
18/**
19 * In-memory data store for execution data. The data can be added through its
20 * {@link IExecutionDataVisitor} interface. If execution data is provided
21 * multiple times for the same class the data is merged, i.e. a block is marked
22 * as executed if it is reported as executed at least once. This allows to merge
23 * coverage date from multiple runs. A instance of this class is not thread
24 * safe.
25 *
26 * @author Marc R. Hoffmann
27 * @version 0.4.1.20101007204400
28 */
29public final class ExecutionDataStore implements IExecutionDataVisitor {
30
31 private final Map<Long, ExecutionData> entries = new HashMap<Long, ExecutionData>();
32
33 /**
34 * Adds the given {@link ExecutionData} object into the store. If there is
35 * already execution data with this same class id, this structure is merged
36 * with the given one.
37 *
38 * @param data
39 * execution data to add or merge
40 * @throws IllegalStateException
41 * if the given {@link ExecutionData} object is not compatible
42 * to a corresponding one, that is already contained
43 * @see ExecutionData#assertCompatibility(long, String, int)
44 */
45 public void put(final ExecutionData data) throws IllegalStateException {
46 final Long id = Long.valueOf(data.getId());
47 final ExecutionData entry = entries.get(id);
48 if (entry == null) {
49 entries.put(id, data);
50 } else {
51 entry.merge(data);
52 }
53 }
54
55 /**
56 * Returns the {@link ExecutionData} entry with the given id if it exists in
57 * this store.
58 *
59 * @param id
60 * class id
61 * @return execution data or <code>null</code>
62 */
63 public ExecutionData get(final long id) {
64 return entries.get(Long.valueOf(id));
65 }
66
67 /**
68 * Returns the coverage data for the class with the given identifier. If
69 * there is no data available under the given id a new entry is created.
70 *
71 * @param id
72 * class identifier
73 * @param name
74 * VM name of the class
75 * @param dataLength
76 * probe data length
77 * @return execution data
78 */
79 public ExecutionData get(final Long id, final String name,
80 final int dataLength) {
81 ExecutionData entry = entries.get(id);
82 if (entry == null) {
83 entry = new ExecutionData(id.longValue(), name, dataLength);
84 entries.put(id, entry);
85 } else {
86 entry.assertCompatibility(id.longValue(), name, dataLength);
87 }
88 return entry;
89 }
90
91 /**
92 * Resets all execution data probes, i.e. marks them as not executed. The
93 * execution data objects itself are not removed.
94 */
95 public void reset() {
96 for (final ExecutionData executionData : this.entries.values()) {
97 executionData.reset();
98 }
99 }
100
101 /**
102 * Returns a collection that represents current contents of the store.
103 *
104 * @return current contents
105 */
106 public Collection<ExecutionData> getContents() {
107 return entries.values();
108 }
109
110 /**
111 * Writes the content of the store to the given visitor interface.
112 *
113 * @param visitor
114 * interface to write content to
115 */
116 public void accept(final IExecutionDataVisitor visitor) {
117 for (final ExecutionData data : entries.values()) {
118 visitor.visitClassExecution(data);
119 }
120 }
121
122 // === IExecutionDataVisitor ===
123
124 public void visitClassExecution(final ExecutionData data) {
125 put(data);
126 }
127}