View Javadoc

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 }