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 }