New constructor that enables one to customize the behaviour at counter

exhaustion (namely, select which exception to throw).


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1167387 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2011-09-09 23:01:59 +00:00
parent 8f09fa850a
commit 8929c05521
2 changed files with 76 additions and 14 deletions

View File

@ -19,8 +19,12 @@ package org.apache.commons.math.util;
import org.apache.commons.math.exception.MaxCountExceededException; import org.apache.commons.math.exception.MaxCountExceededException;
/** /**
* Utility that increments a counter until a maximum is reached, at which * Utility that increments a counter until a maximum is reached, at
* point it will throw an exception. * which point, the instance will by default throw a
* {@link MaxCountExceededException}.
* However, the user is able to override this behaviour by defining a
* custom {@link MaxCountExceededCallback callback}, in order to e.g.
* select which exception must be thrown.
* *
* @version $Id$ * @version $Id$
* @since 3.0 * @since 3.0
@ -33,7 +37,11 @@ public class Incrementor {
/** /**
* Current count. * Current count.
*/ */
private int count; private int count = 0;
/**
* Function called at counter exhaustion.
*/
private final MaxCountExceededCallback maxCountCallback;
/** /**
* Default constructor. * Default constructor.
@ -50,12 +58,30 @@ public class Incrementor {
* @param max Maximal count. * @param max Maximal count.
*/ */
public Incrementor(int max) { public Incrementor(int max) {
maximalCount = max; this(max,
count = 0; new MaxCountExceededCallback() {
/** {@inheritDoc} */
public void trigger(int max) {
throw new MaxCountExceededException(max);
}
});
} }
/** /**
* Set the upper limit for the counter. * Defines a maximal count and a callback method to be triggered at
* counter exhaustion.
*
* @param max Maximal count.
* @param cb Function to be called when the maximal count has been reached.
*/
public Incrementor(int max,
MaxCountExceededCallback cb) {
maximalCount = max;
maxCountCallback = cb;
}
/**
* Sets the upper limit for the counter.
* This does not automatically reset the current count to zero (see * This does not automatically reset the current count to zero (see
* {@link #resetCount()}). * {@link #resetCount()}).
* *
@ -66,7 +92,7 @@ public class Incrementor {
} }
/** /**
* Get the upper limit of the counter. * Gets the upper limit of the counter.
* *
* @return the counter upper limit. * @return the counter upper limit.
*/ */
@ -75,7 +101,7 @@ public class Incrementor {
} }
/** /**
* Get the current count. * Gets the current count.
* *
* @return the current count. * @return the current count.
*/ */
@ -84,7 +110,7 @@ public class Incrementor {
} }
/** /**
* Check whether a single increment is allowed. * Checks whether a single increment is allowed.
* *
* @return {@code false} if the next call to {@link #incrementCount(int) * @return {@code false} if the next call to {@link #incrementCount(int)
* incrementCount} will trigger a {@code MaxCountExceededException}, * incrementCount} will trigger a {@code MaxCountExceededException},
@ -95,7 +121,7 @@ public class Incrementor {
} }
/** /**
* Perform multiple increments. * Performs multiple increments.
* See the other {@link #incrementCount() incrementCount} method). * See the other {@link #incrementCount() incrementCount} method).
* *
* @param value Number of increments. * @param value Number of increments.
@ -108,20 +134,41 @@ public class Incrementor {
} }
/** /**
* Add one to the current iteration count. * Adds one to the current iteration count.
* At counter exhaustion, this method will call the
* {@link MaxCountExceededCallback#trigger(int) trigger} method of the
* callback object passed to the
* {@link #Incrementor(int,MaxCountExceededCallback) constructor}.
* If not explictly set, a default callback is used that will throw
* a {@code MaxCountExceededException}.
* *
* @throws MaxCountExceededException at counter exhaustion. * @throws MaxCountExceededException at counter exhaustion, unless a
* custom {@link MaxCountExceededCallback callback} has been set at
* construction.
*/ */
public void incrementCount() { public void incrementCount() {
if (++count > maximalCount) { if (++count > maximalCount) {
throw new MaxCountExceededException(maximalCount); maxCountCallback.trigger(maximalCount);
} }
} }
/** /**
* Reset the counter to 0. * Resets the counter to 0.
*/ */
public void resetCount() { public void resetCount() {
count = 0; count = 0;
} }
/**
* Defines a method to be called at counter exhaustion.
* The {@link #trigger(int) trigger} method should usually throw an exception.
*/
public interface MaxCountExceededCallback {
/**
* Function called when the maximal count has been reached.
*
* @param maximalCount Maximal count.
*/
void trigger(int maximalCount);
}
} }

View File

@ -14,6 +14,7 @@
package org.apache.commons.math.util; package org.apache.commons.math.util;
import org.apache.commons.math.exception.MaxCountExceededException; import org.apache.commons.math.exception.MaxCountExceededException;
import org.apache.commons.math.exception.TooManyEvaluationsException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -96,6 +97,20 @@ public class IncrementorTest {
i.incrementCount(); i.incrementCount();
} }
@Test(expected=TooManyEvaluationsException.class)
public void testAlternateException() {
final Incrementor.MaxCountExceededCallback cb
= new Incrementor.MaxCountExceededCallback() {
/** {@inheritDoc} */
public void trigger(int max) {
throw new TooManyEvaluationsException(max);
}
};
final Incrementor i = new Incrementor(0, cb);
i.incrementCount();
}
@Test @Test
public void testReset() { public void testReset() {
final Incrementor i = new Incrementor(); final Incrementor i = new Incrementor();