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.algorithm; 018 019import java.util.NoSuchElementException; 020 021import org.apache.commons.functor.BinaryFunction; 022import org.apache.commons.functor.Predicate; 023import org.apache.commons.functor.Procedure; 024import org.apache.commons.functor.generator.Generator; 025 026/** 027 * Return the first Object in a {@link Generator} matching a {@link Predicate}. 028 * 029 * @param <E> the arguments type. 030 * @version $Revision: 1537906 $ $Date: 2013-11-01 12:47:33 +0100 (Fr, 01 Nov 2013) $ 031 */ 032public final class FindWithinGenerator<E> 033 implements BinaryFunction<Generator<? extends E>, Predicate<? super E>, E> { 034 035 /** 036 * Basic instance. 037 */ 038 public static final FindWithinGenerator<Object> INSTANCE = new FindWithinGenerator<Object>(); 039 040 /** 041 * Helper procedure. 042 * 043 * @param <T> the argument type. 044 */ 045 private static class FindProcedure<T> implements Procedure<T> { 046 /** 047 * The object found, if any. 048 */ 049 private T found; 050 /** 051 * Flag to mark an object has been found. 052 */ 053 private boolean wasFound; 054 /** 055 * The adapted predicate. 056 */ 057 private Predicate<? super T> pred; 058 059 /** 060 * Create a new FindProcedure. 061 * @param pred the adapted predicate. 062 */ 063 public FindProcedure(Predicate<? super T> pred) { 064 this.pred = pred; 065 } 066 067 /** 068 * {@inheritDoc} 069 */ 070 public void run(T obj) { 071 if (!wasFound && pred.test(obj)) { 072 wasFound = true; 073 found = obj; 074 } 075 } 076 } 077 078 /** 079 * Flag to mark the {@link FindWithinGenerator#evaluate(Generator, Predicate)} method must return a user 080 * defined object when the adapted procedure does not find any object. 081 */ 082 private final boolean useIfNone; 083 /** 084 * Object to be returned in the case the adapted procedure does not find any object. 085 */ 086 private final E ifNone; 087 088 /** 089 * Create a new FindWithinGenerator. 090 */ 091 public FindWithinGenerator() { 092 super(); 093 ifNone = null; 094 useIfNone = false; 095 } 096 097 /** 098 * Create a new FindWithinGenerator. 099 * @param ifNone object to return if the Generator contains no matches. 100 */ 101 public FindWithinGenerator(E ifNone) { 102 super(); 103 this.ifNone = ifNone; 104 useIfNone = true; 105 } 106 107 /** 108 * {@inheritDoc} 109 * @param left Generator 110 * @param right Predicate 111 */ 112 public E evaluate(Generator<? extends E> left, Predicate<? super E> right) { 113 FindProcedure<E> findProcedure = new FindProcedure<E>(right); 114 left.run(findProcedure); 115 if (!findProcedure.wasFound) { 116 if (useIfNone) { 117 return ifNone; 118 } 119 throw new NoSuchElementException("No element matching " + right + " was found."); 120 } 121 return findProcedure.found; 122 } 123 124 /** 125 * {@inheritDoc} 126 */ 127 @Override 128 public boolean equals(Object obj) { 129 if (obj == this) { 130 return true; 131 } 132 if (!(obj instanceof FindWithinGenerator<?>)) { 133 return false; 134 } 135 FindWithinGenerator<?> other = (FindWithinGenerator<?>) obj; 136 return other.useIfNone == useIfNone && !useIfNone 137 || (other.ifNone == this.ifNone || other.ifNone != null && other.ifNone.equals(this.ifNone)); 138 } 139 140 /** 141 * {@inheritDoc} 142 */ 143 @Override 144 public int hashCode() { 145 if (!this.useIfNone) { 146 return System.identityHashCode(INSTANCE); 147 } 148 int result = "FindWithinGenerator".hashCode(); 149 result ^= this.ifNone == null ? 0 : this.ifNone.hashCode(); 150 return result; 151 } 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override 157 public String toString() { 158 return "FindWithinGenerator<" + ifNone + "," + useIfNone + ">"; 159 } 160 161 /** 162 * Get a static {@link FindWithinGenerator} instance. 163 * @return {@link FindWithinGenerator} 164 */ 165 public static FindWithinGenerator<Object> instance() { 166 return INSTANCE; 167 } 168}