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