    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 java.util.Collection;
    020    import java.util.concurrent.CopyOnWriteArrayList;
    021
    022    import org.apache.commons.math3.exception.MaxCountExceededException;
    023
    024    /**
    025     * This abstract class provides a general framework for managing iterative
    026     * algorithms. The maximum number of iterations can be set, and methods are
    027     * provided to monitor the current iteration count. A lightweight event
    028     * framework is also provided.
    029     *
    030     * @version $Id: IterationManager.java 1422313 2012-12-15 18:53:41Z psteitz $
    031     */
    032    public class IterationManager {
    033
    034        /** Keeps a count of the number of iterations. */
    035        private final Incrementor iterations;
    036
    037        /** The collection of all listeners attached to this iterative algorithm. */
    038        private final Collection<IterationListener> listeners;
    039
    040        /**
    041         * Creates a new instance of this class.
    042         *
    043         * @param maxIterations the maximum number of iterations
    044         */
    045        public IterationManager(final int maxIterations) {
    046            this.iterations = new Incrementor(maxIterations);
    047            this.listeners = new CopyOnWriteArrayList<IterationListener>();
    048        }
    049
    050        /**
    051         * Creates a new instance of this class.
    052         *
    053         * @param maxIterations the maximum number of iterations
    054         * @param callBack the function to be called when the maximum number of
    055         * iterations has been reached
    056         * @throws org.apache.commons.math3.exception.NullArgumentException if {@code callBack} is {@code null}
    057         * @since 3.1
    058         */
    059        public IterationManager(final int maxIterations,
    060                                final Incrementor.MaxCountExceededCallback callBack) {
    061            this.iterations = new Incrementor(maxIterations, callBack);
    062            this.listeners = new CopyOnWriteArrayList<IterationListener>();
    063        }
    064
    065        /**
    066         * Attaches a listener to this manager.
    067         *
    068         * @param listener A {@code IterationListener} object.
    069         */
    070        public void addIterationListener(final IterationListener listener) {
    071            listeners.add(listener);
    072        }
    073
    074        /**
    075         * Informs all registered listeners that the initial phase (prior to the
    076         * main iteration loop) has been completed.
    077         *
    078         * @param e The {@link IterationEvent} object.
    079         */
    080        public void fireInitializationEvent(final IterationEvent e) {
    081            for (IterationListener l : listeners) {
    082                l.initializationPerformed(e);
    083            }
    084        }
    085
    086        /**
    087         * Informs all registered listeners that a new iteration (in the main
    088         * iteration loop) has been performed.
    089         *
    090         * @param e The {@link IterationEvent} object.
    091         */
    092        public void fireIterationPerformedEvent(final IterationEvent e) {
    093            for (IterationListener l : listeners) {
    094                l.iterationPerformed(e);
    095            }
    096        }
    097
    098        /**
    099         * Informs all registered listeners that a new iteration (in the main
    100         * iteration loop) has been started.
    101         *
    102         * @param e The {@link IterationEvent} object.
    103         */
    104        public void fireIterationStartedEvent(final IterationEvent e) {
    105            for (IterationListener l : listeners) {
    106                l.iterationStarted(e);
    107            }
    108        }
    109
    110        /**
    111         * Informs all registered listeners that the final phase (post-iterations)
    112         * has been completed.
    113         *
    114         * @param e The {@link IterationEvent} object.
    115         */
    116        public void fireTerminationEvent(final IterationEvent e) {
    117            for (IterationListener l : listeners) {
    118                l.terminationPerformed(e);
    119            }
    120        }
    121
    122        /**
    123         * Returns the number of iterations of this solver, 0 if no iterations has
    124         * been performed yet.
    125         *
    126         * @return the number of iterations.
    127         */
    128        public int getIterations() {
    129            return iterations.getCount();
    130        }
    131
    132        /**
    133         * Returns the maximum number of iterations.
    134         *
    135         * @return the maximum number of iterations.
    136         */
    137        public int getMaxIterations() {
    138            return iterations.getMaximalCount();
    139        }
    140
    141        /**
    142         * Increments the iteration count by one, and throws an exception if the
    143         * maximum number of iterations is reached. This method should be called at
    144         * the beginning of a new iteration.
    145         *
    146         * @throws MaxCountExceededException if the maximum number of iterations is
    147         * reached.
    148         */
    149        public void incrementIterationCount()
    150            throws MaxCountExceededException {
    151            iterations.incrementCount();
    152        }
    153
    154        /**
    155         * Removes the specified iteration listener from the list of listeners
    156         * currently attached to {@code this} object. Attempting to remove a
    157         * listener which was <em>not</em> previously registered does not cause any
    158         * error.
    159         *
    160         * @param listener The {@link IterationListener} to be removed.
    161         */
    162        public void removeIterationListener(final IterationListener listener) {
    163            listeners.remove(listener);
    164        }
    165
    166        /**
    167         * Sets the iteration count to 0. This method must be called during the
    168         * initial phase.
    169         */
    170        public void resetIterationCount() {
    171            iterations.resetCount();
    172        }
    173    }