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