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