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}