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 */ 017package org.apache.commons.math3.util; 018 019import org.apache.commons.math3.exception.MaxCountExceededException; 020import 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 * @deprecated Use {@link IntegerSequence.Incrementor} instead. 032 */ 033@Deprecated 034public class Incrementor { 035 /** 036 * Upper limit for the counter. 037 */ 038 private int maximalCount; 039 /** 040 * Current count. 041 */ 042 private int count = 0; 043 /** 044 * Function called at counter exhaustion. 045 */ 046 private final MaxCountExceededCallback maxCountCallback; 047 048 /** 049 * Default constructor. 050 * For the new instance to be useful, the maximal count must be set 051 * by calling {@link #setMaximalCount(int) setMaximalCount}. 052 */ 053 public Incrementor() { 054 this(0); 055 } 056 057 /** 058 * Defines a maximal count. 059 * 060 * @param max Maximal count. 061 */ 062 public Incrementor(int max) { 063 this(max, 064 new MaxCountExceededCallback() { 065 /** {@inheritDoc} */ 066 public void trigger(int max) throws MaxCountExceededException { 067 throw new MaxCountExceededException(max); 068 } 069 }); 070 } 071 072 /** 073 * Defines a maximal count and a callback method to be triggered at 074 * counter exhaustion. 075 * 076 * @param max Maximal count. 077 * @param cb Function to be called when the maximal count has been reached. 078 * @throws NullArgumentException if {@code cb} is {@code null} 079 */ 080 public Incrementor(int max, MaxCountExceededCallback cb) 081 throws NullArgumentException { 082 if (cb == null){ 083 throw new NullArgumentException(); 084 } 085 maximalCount = max; 086 maxCountCallback = cb; 087 } 088 089 /** 090 * Sets the upper limit for the counter. 091 * This does not automatically reset the current count to zero (see 092 * {@link #resetCount()}). 093 * 094 * @param max Upper limit of the counter. 095 */ 096 public void setMaximalCount(int max) { 097 maximalCount = max; 098 } 099 100 /** 101 * Gets the upper limit of the counter. 102 * 103 * @return the counter upper limit. 104 */ 105 public int getMaximalCount() { 106 return maximalCount; 107 } 108 109 /** 110 * Gets the current count. 111 * 112 * @return the current count. 113 */ 114 public int getCount() { 115 return count; 116 } 117 118 /** 119 * Checks whether a single increment is allowed. 120 * 121 * @return {@code false} if the next call to {@link #incrementCount(int) 122 * incrementCount} will trigger a {@code MaxCountExceededException}, 123 * {@code true} otherwise. 124 */ 125 public boolean canIncrement() { 126 return count < maximalCount; 127 } 128 129 /** 130 * Performs multiple increments. 131 * See the other {@link #incrementCount() incrementCount} method). 132 * 133 * @param value Number of increments. 134 * @throws MaxCountExceededException at counter exhaustion. 135 */ 136 public void incrementCount(int value) throws MaxCountExceededException { 137 for (int i = 0; i < value; i++) { 138 incrementCount(); 139 } 140 } 141 142 /** 143 * Adds one to the current iteration count. 144 * At counter exhaustion, this method will call the 145 * {@link MaxCountExceededCallback#trigger(int) trigger} method of the 146 * callback object passed to the 147 * {@link #Incrementor(int,MaxCountExceededCallback) constructor}. 148 * If not explictly set, a default callback is used that will throw 149 * a {@code MaxCountExceededException}. 150 * 151 * @throws MaxCountExceededException at counter exhaustion, unless a 152 * custom {@link MaxCountExceededCallback callback} has been set at 153 * construction. 154 */ 155 public void incrementCount() throws MaxCountExceededException { 156 if (++count > maximalCount) { 157 maxCountCallback.trigger(maximalCount); 158 } 159 } 160 161 /** 162 * Resets the counter to 0. 163 */ 164 public void resetCount() { 165 count = 0; 166 } 167 168 /** 169 * Defines a method to be called at counter exhaustion. 170 * The {@link #trigger(int) trigger} method should usually throw an exception. 171 */ 172 public interface MaxCountExceededCallback { 173 /** 174 * Function called when the maximal count has been reached. 175 * 176 * @param maximalCount Maximal count. 177 * @throws MaxCountExceededException at counter exhaustion 178 */ 179 void trigger(int maximalCount) throws MaxCountExceededException; 180 } 181 182 /** Create an instance that delegates everything to a {@link IntegerSequence.Incrementor}. 183 * <p> 184 * This factory method is intended only as a temporary hack for internal use in 185 * Apache Commons Math 3.X series, when {@code Incrementor} is required in 186 * interface (as a return value or in protected fields). It should <em>not</em> 187 * be used in other cases. The {@link IntegerSequence.Incrementor} class should 188 * be used instead of {@code Incrementor}. 189 * </p> 190 * <p> 191 * All methods are mirrored to the underlying {@link IntegerSequence.Incrementor}, 192 * as long as neither {@link #setMaximalCount(int)} nor {@link #resetCount()} are called. 193 * If one of these two methods is called, the created instance becomes independent 194 * of the {@link IntegerSequence.Incrementor} used at creation. The rationale is that 195 * {@link IntegerSequence.Incrementor} cannot change their maximal count and cannot be reset. 196 * </p> 197 * @param incrementor wrapped {@link IntegerSequence.Incrementor} 198 * @return an incrementor wrapping an {@link IntegerSequence.Incrementor} 199 * @since 3.6 200 */ 201 public static Incrementor wrap(final IntegerSequence.Incrementor incrementor) { 202 return new Incrementor() { 203 204 /** Underlying incrementor. */ 205 private IntegerSequence.Incrementor delegate; 206 207 { 208 // set up matching values at initialization 209 delegate = incrementor; 210 super.setMaximalCount(delegate.getMaximalCount()); 211 super.incrementCount(delegate.getCount()); 212 } 213 214 /** {@inheritDoc} */ 215 @Override 216 public void setMaximalCount(int max) { 217 super.setMaximalCount(max); 218 delegate = delegate.withMaximalCount(max); 219 } 220 221 /** {@inheritDoc} */ 222 @Override 223 public void resetCount() { 224 super.resetCount(); 225 delegate = delegate.withStart(0); 226 } 227 228 /** {@inheritDoc} */ 229 @Override 230 public void incrementCount() { 231 super.incrementCount(); 232 delegate.increment(); 233 } 234 235 }; 236 } 237 238}