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.functor.core;
018    
019    import org.apache.commons.functor.BinaryPredicate;
020    import org.apache.commons.functor.Predicate;
021    import org.apache.commons.functor.UnaryPredicate;
022    
023    /**
024     * A predicate that returns <code>true</code>
025     * the first <i>n</i> times it is invoked.
026     *
027     * @since 1.0
028     * @version $Revision: 1160412 $ $Date: 2011-08-22 22:10:41 +0200 (Mon, 22 Aug 2011) $
029     * @author Jason Horman (jason@jhorman.org)
030     * @author Rodney Waldhoff
031     */
032    
033    public final class Limit implements Predicate, UnaryPredicate<Object>, BinaryPredicate<Object, Object> {
034        // instance variables
035        //---------------------------------------------------------------
036        /**
037         * The max number of times the predicate can be invoked.
038         */
039        private final int max;
040        /**
041         * The current number of times the predicate has been invoked.
042         */
043        private int current;
044    
045        /**
046         * Create a new Limit.
047         * @param count limit
048         */
049        public Limit(int count) {
050            if (count < 0) {
051                throw new IllegalArgumentException("Argument must be a non-negative integer.");
052            }
053            this.max = count;
054        }
055    
056        /**
057         * {@inheritDoc}
058         */
059        public synchronized boolean test() {
060            // stop incrementing when we've hit max, so we don't loop around
061            if (current < max) {
062                current++;
063                return true;
064            }
065            return false;
066        }
067    
068        /**
069         * {@inheritDoc}
070         */
071        public boolean test(Object obj) {
072            return test();
073        }
074    
075        /**
076         * {@inheritDoc}
077         */
078        public boolean test(Object a, Object b) {
079            return test();
080        }
081    
082        /**
083         * {@inheritDoc}
084         */
085        public String toString() {
086            return "Limit<" + max + ">";
087        }
088    
089        //default == equals/hashCode due to statefulness
090    }