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}