/******************************************************************************* * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * Marc R. Hoffmann - initial API and implementation * *******************************************************************************/ package org.jacoco.core.data; import static java.lang.String.format; import java.util.Arrays; /** * Execution data for a single Java class. While instances are immutable care * has to be taken about the probe data array of type boolean[] * which can be modified. */ // BEGIN android-change public final class ExecutionData implements IExecutionData { // END android-change private final long id; private final String name; private final boolean[] probes; /** * Creates a new {@link ExecutionData} object with the given probe data. * * @param id * class identifier * @param name * VM name * @param probes * probe data */ public ExecutionData(final long id, final String name, final boolean[] probes) { this.id = id; this.name = name; this.probes = probes; } /** * Creates a new {@link ExecutionData} object with the given probe data * length. All probes are set to false. * * @param id * class identifier * @param name * VM name * @param probeCount * probe count */ public ExecutionData(final long id, final String name, final int probeCount) { this.id = id; this.name = name; this.probes = new boolean[probeCount]; } /** * Return the unique identifier for this class. The identifier is the CRC64 * checksum of the raw class file definition. * * @return class identifier */ public long getId() { return id; } /** * The VM name of the class. * * @return VM name */ public String getName() { return name; } // BEGIN android-change /** * Returns a copy of the current probe values. * * @return copy of the probe array */ public boolean[] getProbesCopy() { return Arrays.copyOf(probes, probes.length); } /** * The number of probes in this ExecutionData. * * @return the number of probes */ public int getProbeCount() { return probes.length; } /** * Returns the execution data probes. A value of true indicates * that the corresponding probe was executed. * * @return probe data */ public boolean getProbe(final int index) { return probes[index]; } /** * Sets the execution data probe for a given index to true. */ public void setProbe(final int index) { probes[index] = true; } // END android-change /** * Sets all probes to false. */ public void reset() { Arrays.fill(probes, false); } /** * Checks whether any probe has been hit. * * @return true, if at least one probe has been hit */ public boolean hasHits() { for (final boolean p : probes) { if (p) { return true; } } return false; } /** * Merges the given execution data into the probe data of this object. I.e. * a probe entry in this object is marked as executed (true) if * this probe or the corresponding other probe was executed. So the result * is * *
	 * A or B
	 * 
* * The probe array of the other object is not modified. * * @param other * execution data to merge */ // BEGIN android-change public void merge(final IExecutionData other) { // END android-change merge(other, true); } /** * Merges the given execution data into the probe data of this object. A * probe in this object is set to the value of flag if the * corresponding other probe was executed. For flag==true this * corresponds to * *
	 * A or B
	 * 
* * For flag==false this can be considered as a subtraction * *
	 * A and not B
	 * 
* * The probe array of the other object is not modified. * * @param other * execution data to merge * @param flag * merge mode */ public void merge(final IExecutionData other, final boolean flag) { // BEGIN android-change assertCompatibility(other.getId(), other.getName(), other.getProbeCount()); final boolean[] otherData = other.getProbesCopy(); // END android-change for (int i = 0; i < probes.length; i++) { if (otherData[i]) { probes[i] = flag; } } } /** * Asserts that this execution data object is compatible with the given * parameters. The purpose of this check is to detect a very unlikely class * id collision. * * @param id * other class id, must be the same * @param name * other name, must be equal to this name * @param probecount * probe data length, must be the same as for this data * @throws IllegalStateException * if the given parameters do not match this instance */ public void assertCompatibility(final long id, final String name, final int probecount) throws IllegalStateException { if (this.id != id) { throw new IllegalStateException( format("Different ids (%016x and %016x).", Long.valueOf(this.id), Long.valueOf(id))); } if (!this.name.equals(name)) { throw new IllegalStateException( format("Different class names %s and %s for id %016x.", this.name, name, Long.valueOf(id))); } if (this.probes.length != probecount) { throw new IllegalStateException(format( "Incompatible execution data for class %s with id %016x.", name, Long.valueOf(id))); } } @Override public String toString() { return String.format("ExecutionData[name=%s, id=%016x]", name, Long.valueOf(id)); } }