CounterImpl.java

    1/*******************************************************************************
    2 * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others
    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 * $Id: $
   12 *******************************************************************************/
   13package org.jacoco.core.analysis;
   14
   15/**
   16 * {@link ICounter} implementations. Implementing a factory pattern allows to
   17 * share counter instances.
   18 * 
   19 * @author Marc R. Hoffmann
   20 * @version $Revision: $
   21 */
   22public abstract class CounterImpl extends AbstractCounter {
   23
   24    /** Max counter value for which singletons are created */
   25    private static final int SINGLETON_LIMIT = 10;
   26
   27    private static final CounterImpl[][] SINGLETONS = new CounterImpl[SINGLETON_LIMIT + 1][];
   28
   29    static {
   30        for (int i = 0; i <= SINGLETON_LIMIT; i++) {
   31            SINGLETONS[i] = new CounterImpl[i + 1];
   32            for (int j = 0; j <= i; j++) {
   33                SINGLETONS[i][j] = new Fix(i, j);
   34            }
   35        }
   36    }
   37
   38    /** Constant for Counter with 0/0 values. */
   39    public static final CounterImpl COUNTER_0_0 = SINGLETONS[0][0];
   40
   41    /**
   42     * Mutable version of the counter.
   43     */
   44    private static class Var extends CounterImpl {
   45        public Var(final int total, final int covered) {
   46            super(total, covered);
   47        }
   48
   49        @Override
   50        public CounterImpl increment(final ICounter counter) {
   51            this.total += counter.getTotalCount();
   52            this.covered += counter.getCoveredCount();
   53            return this;
   54        }
   55    }
   56
   57    /**
   58     * Immutable version of the counter.
   59     */
   60    private static class Fix extends CounterImpl {
   61        public Fix(final int total, final int covered) {
   62            super(total, covered);
   63        }
   64
   65        @Override
   66        public CounterImpl increment(final ICounter counter) {
   67            return getInstance(this.total + counter.getTotalCount(),
   68                    this.covered + counter.getCoveredCount());
   69        }
   70    }
   71
   72    /**
   73     * Factory method to retrieve a counter with the given number of items.
   74     * 
   75     * @param total
   76     *            total number of items
   77     * @param covered
   78     *            covered number of items
   79     * @return counter instance
   80     */
   81    public static CounterImpl getInstance(final int total, final int covered) {
   82        if (total <= SINGLETON_LIMIT && covered <= total) {
   83            return SINGLETONS[total][covered];
   84        } else {
   85            return new Var(total, covered);
   86        }
   87    }
   88
   89    /**
   90     * Factory method to retrieve a clone ot the given counter.
   91     * 
   92     * @param counter
   93     *            counter to copy
   94     * @return counter instance
   95     */
   96    public static CounterImpl getInstance(final ICounter counter) {
   97        return getInstance(counter.getTotalCount(), counter.getCoveredCount());
   98    }
   99
  100    /**
  101     * Factory method to retrieve a counter with the given number of items.
  102     * 
  103     * @param total
  104     *            total number of items
  105     * @param covered
  106     *            <code>true</code>, if all items are covered
  107     * @return counter instance
  108     */
  109    public static CounterImpl getInstance(final int total, final boolean covered) {
  110        return getInstance(total, covered ? total : 0);
  111    }
  112
  113    /**
  114     * Factory method to retrieve a counter for a single item.
  115     * 
  116     * @param covered
  117     *            <code>true</code>, if the item is covered
  118     * @return counter instance
  119     */
  120    public static CounterImpl getInstance(final boolean covered) {
  121        return getInstance(1, covered ? 1 : 0);
  122    }
  123
  124    /**
  125     * Creates a new instance with the given figures.
  126     * 
  127     * @param total
  128     *            total number of items
  129     * @param covered
  130     *            covered number of items
  131     */
  132    protected CounterImpl(final int total, final int covered) {
  133        super(total, covered);
  134    }
  135
  136    /**
  137     * Returns a counter with values incremented by the numbers of the given
  138     * counter. It is up to the implementation whether this counter instance is
  139     * modified or a new instance is returned.
  140     * 
  141     * @param counter
  142     *            number of additional total and covered items
  143     * @return counter instance with incremented values
  144     */
  145    public abstract CounterImpl increment(final ICounter counter);
  146
  147}