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}