1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.functor.core; 18 19 import java.util.concurrent.atomic.AtomicInteger; 20 21 import org.apache.commons.functor.BinaryPredicate; 22 import org.apache.commons.functor.NullaryPredicate; 23 import org.apache.commons.functor.Predicate; 24 import org.apache.commons.lang3.Validate; 25 26 /** 27 * A predicate that returns <code>false</code> 28 * the first <i>n</i> times it is invoked, and 29 * <code>true</code> thereafter. 30 * 31 * @since 1.0 32 * @version $Revision: 1539877 $ $Date: 2013-11-08 01:20:07 +0100 (Fr, 08 Nov 2013) $ 33 */ 34 public final class Offset implements NullaryPredicate, Predicate<Object>, 35 BinaryPredicate<Object, Object> { 36 // instance variables 37 //--------------------------------------------------------------- 38 /** 39 * The number of times the predicate must return {@code false}. 40 */ 41 private final int min; 42 /** 43 * The current number of times the predicate has been invoked. 44 */ 45 private AtomicInteger state = new AtomicInteger(); 46 47 /** 48 * Create a new Offset. 49 * @param count offset 50 */ 51 public Offset(int count) { 52 Validate.isTrue(count >= 0, "Argument must be a non-negative integer."); 53 this.min = count; 54 } 55 56 /** 57 * {@inheritDoc} 58 */ 59 public boolean test() { 60 // stop incrementing when we've hit max, so we don't loop around 61 if (state.get() < min) { 62 state.incrementAndGet(); 63 return false; 64 } 65 return true; 66 } 67 68 /** 69 * {@inheritDoc} 70 */ 71 public boolean test(Object obj) { 72 return test(); 73 } 74 75 /** 76 * {@inheritDoc} 77 */ 78 public boolean test(Object a, Object b) { 79 return test(); 80 } 81 82 /** 83 * {@inheritDoc} 84 */ 85 @Override 86 public boolean equals(Object obj) { 87 if (obj == this) { 88 return true; 89 } 90 if (!(obj instanceof Offset)) { 91 return false; 92 } 93 Offset other = (Offset) obj; 94 return other.min == min; 95 } 96 97 /** 98 * {@inheritDoc} 99 */ 100 @Override 101 public int hashCode() { 102 int result = "Offset".hashCode(); 103 result <<= 2; 104 result ^= min; 105 return result; 106 } 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override 112 public String toString() { 113 return "Offset<" + min + ">"; 114 } 115 116 //default == equals/hashCode due to statefulness 117 }