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.algorithm;
18
19 import java.io.Serializable;
20 import java.util.NoSuchElementException;
21
22 import org.apache.commons.functor.BinaryFunction;
23 import org.apache.commons.functor.UnaryPredicate;
24 import org.apache.commons.functor.UnaryProcedure;
25 import org.apache.commons.functor.generator.Generator;
26
27 /**
28 * Return the first Object in a {@link Generator} matching a {@link UnaryPredicate}.
29 *
30 * @param <E> the arguments type.
31 * @version $Revision: 1160622 $ $Date: 2011-08-23 13:03:37 +0200 (Tue, 23 Aug 2011) $
32 */
33 public final class FindWithinGenerator<E>
34 implements BinaryFunction<Generator<? extends E>, UnaryPredicate<? super E>, E>, Serializable {
35
36 /**
37 * Basic instance.
38 */
39 public static final FindWithinGenerator<Object> INSTANCE = new FindWithinGenerator<Object>();
40
41 /**
42 * serialVersionUID declaration.
43 */
44 private static final long serialVersionUID = -2824239991638326134L;
45
46 /**
47 * Helper procedure.
48 *
49 * @param <T> the argument type.
50 */
51 private static class FindProcedure<T> implements UnaryProcedure<T> {
52 /**
53 * The object found, if any.
54 */
55 private T found;
56 /**
57 * Flag to mark an object has been found.
58 */
59 private boolean wasFound;
60 /**
61 * The adapted predicate.
62 */
63 private UnaryPredicate<? super T> pred;
64
65 /**
66 * Create a new FindProcedure.
67 * @param pred the adapted predicate.
68 */
69 public FindProcedure(UnaryPredicate<? super T> pred) {
70 this.pred = pred;
71 }
72
73 /**
74 * {@inheritDoc}
75 */
76 public void run(T obj) {
77 if (!wasFound && pred.test(obj)) {
78 wasFound = true;
79 found = obj;
80 }
81 }
82 }
83
84 /**
85 * Flag to mark the {@link FindWithinGenerator#evaluate(Generator, UnaryPredicate)} method must return a user
86 * defined object when the adapted procedure does not find any object.
87 */
88 private final boolean useIfNone;
89 /**
90 * Object to be returned in the case the adapted procedure does not find any object.
91 */
92 private final E ifNone;
93
94 /**
95 * Create a new FindWithinGenerator.
96 */
97 public FindWithinGenerator() {
98 super();
99 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 }