001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math3.util;
018
019 import org.apache.commons.math3.exception.MaxCountExceededException;
020 import org.apache.commons.math3.exception.NullArgumentException;
021
022 /**
023 * Utility that increments a counter until a maximum is reached, at
024 * which point, the instance will by default throw a
025 * {@link MaxCountExceededException}.
026 * However, the user is able to override this behaviour by defining a
027 * custom {@link MaxCountExceededCallback callback}, in order to e.g.
028 * select which exception must be thrown.
029 *
030 * @since 3.0
031 * @version $Id: Incrementor.java 1364389 2012-07-22 18:19:26Z tn $
032 */
033 public class Incrementor {
034 /**
035 * Upper limit for the counter.
036 */
037 private int maximalCount;
038 /**
039 * Current count.
040 */
041 private int count = 0;
042 /**
043 * Function called at counter exhaustion.
044 */
045 private final MaxCountExceededCallback maxCountCallback;
046
047 /**
048 * Default constructor.
049 * For the new instance to be useful, the maximal count must be set
050 * by calling {@link #setMaximalCount(int) setMaximalCount}.
051 */
052 public Incrementor() {
053 this(0);
054 }
055
056 /**
057 * Defines a maximal count.
058 *
059 * @param max Maximal count.
060 */
061 public Incrementor(int max) {
062 this(max,
063 new MaxCountExceededCallback() {
064 /** {@inheritDoc} */
065 public void trigger(int max) {
066 throw new MaxCountExceededException(max);
067 }
068 });
069 }
070
071 /**
072 * Defines a maximal count and a callback method to be triggered at
073 * counter exhaustion.
074 *
075 * @param max Maximal count.
076 * @param cb Function to be called when the maximal count has been reached.
077 * @throws NullArgumentException if {@code cb} is {@code null}
078 */
079 public Incrementor(int max,
080 MaxCountExceededCallback cb) {
081 if (cb == null){
082 throw new NullArgumentException();
083 }
084 maximalCount = max;
085 maxCountCallback = cb;
086 }
087
088 /**
089 * Sets the upper limit for the counter.
090 * This does not automatically reset the current count to zero (see
091 * {@link #resetCount()}).
092 *
093 * @param max Upper limit of the counter.
094 */
095 public void setMaximalCount(int max) {
096 maximalCount = max;
097 }
098
099 /**
100 * Gets the upper limit of the counter.
101 *
102 * @return the counter upper limit.
103 */
104 public int getMaximalCount() {
105 return maximalCount;
106 }
107
108 /**
109 * Gets the current count.
110 *
111 * @return the current count.
112 */
113 public int getCount() {
114 return count;
115 }
116
117 /**
118 * Checks whether a single increment is allowed.
119 *
120 * @return {@code false} if the next call to {@link #incrementCount(int)
121 * incrementCount} will trigger a {@code MaxCountExceededException},
122 * {@code true} otherwise.
123 */
124 public boolean canIncrement() {
125 return count < maximalCount;
126 }
127
128 /**
129 * Performs multiple increments.
130 * See the other {@link #incrementCount() incrementCount} method).
131 *
132 * @param value Number of increments.
133 * @throws MaxCountExceededException at counter exhaustion.
134 */
135 public void incrementCount(int value) {
136 for (int i = 0; i < value; i++) {
137 incrementCount();
138 }
139 }
140
141 /**
142 * Adds one to the current iteration count.
143 * At counter exhaustion, this method will call the
144 * {@link MaxCountExceededCallback#trigger(int) trigger} method of the
145 * callback object passed to the
146 * {@link #Incrementor(int,MaxCountExceededCallback) constructor}.
147 * If not explictly set, a default callback is used that will throw
148 * a {@code MaxCountExceededException}.
149 *
150 * @throws MaxCountExceededException at counter exhaustion, unless a
151 * custom {@link MaxCountExceededCallback callback} has been set at
152 * construction.
153 */
154 public void incrementCount() {
155 if (++count > maximalCount) {
156 maxCountCallback.trigger(maximalCount);
157 }
158 }
159
160 /**
161 * Resets the counter to 0.
162 */
163 public void resetCount() {
164 count = 0;
165 }
166
167 /**
168 * Defines a method to be called at counter exhaustion.
169 * The {@link #trigger(int) trigger} method should usually throw an exception.
170 */
171 public interface MaxCountExceededCallback {
172 /**
173 * Function called when the maximal count has been reached.
174 *
175 * @param maximalCount Maximal count.
176 */
177 void trigger(int maximalCount);
178 }
179 }