ExecutionData.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 static java.lang.String.format;
15
16import java.util.Arrays;
17
18/**
19 * Execution data for a single Java class. While instances are immutable care
20 * has to be taken about the probe data array of type <code>boolean[]</code>
21 * which can be modified.
22 *
23 * @author Marc R. Hoffmann
24 * @version 0.4.1.20101007204400
25 */
26public final class ExecutionData {
27
28 private final long id;
29
30 private final String name;
31
32 private final boolean[] data;
33
34 /**
35 * Creates a new {@link ExecutionData} object with the given probe data.
36 *
37 * @param id
38 * class identifier
39 * @param name
40 * VM name
41 * @param data
42 * probe data
43 */
44 public ExecutionData(final long id, final String name, final boolean[] data) {
45 this.id = id;
46 this.name = name;
47 this.data = data;
48 }
49
50 /**
51 * Creates a new {@link ExecutionData} object with the given probe data
52 * length. All probes are set to <code>false</code>.
53 *
54 * @param id
55 * class identifier
56 * @param name
57 * VM name
58 * @param dataLength
59 * probe data length
60 */
61 public ExecutionData(final long id, final String name, final int dataLength) {
62 this.id = id;
63 this.name = name;
64 this.data = new boolean[dataLength];
65 }
66
67 /**
68 * Return the unique identifier for this class. The identifier is the CRC64
69 * checksum of the raw class file definition.
70 *
71 * @return class identifier
72 */
73 public long getId() {
74 return id;
75 }
76
77 /**
78 * The VM name of the class.
79 *
80 * @return VM name
81 */
82 public String getName() {
83 return name;
84 }
85
86 /**
87 * Returns the execution data probes. A value of <code>true</code> indicates
88 * that the corresponding probe was executed.
89 *
90 * @return execution data
91 */
92 public boolean[] getData() {
93 return data;
94 }
95
96 /**
97 * Sets all probe data entries to <code>false</code>.
98 */
99 public void reset() {
100 Arrays.fill(data, false);
101 }
102
103 /**
104 * Merges the given execution data into the probe data of this object. I.e.
105 * a probe entry in this object is marked as executed (<code>true</code>) if
106 * this probe or the corresponding other probe was executed. The probe array
107 * of the other object is not modified.
108 *
109 * @param other
110 */
111 public void merge(final ExecutionData other) {
112 assertCompatibility(other.getId(), other.getName(),
113 other.getData().length);
114 final boolean[] otherData = other.getData();
115 for (int i = 0; i < data.length; i++) {
116 if (otherData[i]) {
117 data[i] = true;
118 }
119 }
120 }
121
122 /**
123 * Asserts that this execution data object is compatible with the given
124 * parameters. The purpose of this check is to detect a very unlikely class
125 * id collision.
126 *
127 * @param id
128 * other class id, must be the same
129 * @param name
130 * other name, must be equal to this name
131 * @param dataLength
132 * probe data length, must be the same as for this data
133 * @throws IllegalStateException
134 * if the given parameters do not match this instance
135 */
136 public void assertCompatibility(final long id, final String name,
137 final int dataLength) throws IllegalStateException {
138 if (this.id != id) {
139 throw new IllegalStateException(format(
140 "Different ids (%016x and %016x).", Long.valueOf(this.id),
141 Long.valueOf(id)));
142 }
143 if (!this.name.equals(name)) {
144 throw new IllegalStateException(format(
145 "Different class names %s and %s for id %016x.", this.name,
146 name, Long.valueOf(id)));
147 }
148 if (this.data.length != dataLength) {
149 throw new IllegalStateException(format(
150 "Incompatible execution data for class %s with id %016x.",
151 name, Long.valueOf(id)));
152 }
153 }
154
155 @Override
156 public String toString() {
157 return String.format("ExecutionData [name=%s, id=%016x]", name, Long.valueOf(id));
158 }
159}