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.functor.core;
018
019import java.io.Serializable;
020
021import org.apache.commons.functor.BinaryPredicate;
022import org.apache.commons.functor.Predicate;
023import org.apache.commons.functor.UnaryPredicate;
024
025/**
026 * A predicate that returns <code>false</code>
027 * the first <i>n</i> times it is invoked, and
028 * <code>true</code> thereafter.
029 *
030 * @since 1.0
031 * @version $Revision: 1348547 $ $Date: 2012-06-10 04:06:11 -0400 (Sun, 10 Jun 2012) $
032 */
033public final class Offset implements Predicate, UnaryPredicate<Object>, BinaryPredicate<Object, Object>, Serializable {
034    // static attributes
035    // ------------------------------------------------------------------------
036    /**
037     * serialVersionUID declaration.
038     */
039    private static final long serialVersionUID = 5800706757874735854L;
040
041    // instance variables
042    //---------------------------------------------------------------
043    /**
044     * The number of times the predicate must return {@code false}.
045     */
046    private final int min;
047    /**
048     * The current number of times the predicate has been invoked.
049     */
050    private int current;
051
052    /**
053     * Create a new Offset.
054     * @param count offset
055     */
056    public Offset(int count) {
057        if (count < 0) {
058            throw new IllegalArgumentException("Argument must be a non-negative integer.");
059        }
060        this.min = count;
061    }
062
063    /**
064     * {@inheritDoc}
065     */
066    public synchronized boolean test() {
067        // stop incrementing when we've hit max, so we don't loop around
068        if (current < min) {
069            current++;
070            return false;
071        }
072        return true;
073    }
074
075    /**
076     * {@inheritDoc}
077     */
078    public boolean test(Object obj) {
079        return test();
080    }
081
082    /**
083     * {@inheritDoc}
084     */
085    public boolean test(Object a, Object b) {
086        return test();
087    }
088
089    /**
090     * {@inheritDoc}
091     */
092    @Override
093    public boolean equals(Object obj) {
094        if (obj == this) {
095            return true;
096        }
097        if (!(obj instanceof Offset)) {
098            return false;
099        }
100        Offset other = (Offset) obj;
101        return other.min == min;
102    }
103
104    /**
105     * {@inheritDoc}
106     */
107    @Override
108    public int hashCode() {
109        int result = "Offset".hashCode();
110        result <<= 2;
111        result ^= min;
112        return result;
113    }
114
115    /**
116     * {@inheritDoc}
117     */
118    @Override
119    public String toString() {
120        return "Offset<" + min + ">";
121    }
122
123    //default == equals/hashCode due to statefulness
124}