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  
21  import org.apache.commons.functor.BinaryFunction;
22  import org.apache.commons.functor.UnaryFunction;
23  import org.apache.commons.functor.UnaryProcedure;
24  import org.apache.commons.functor.generator.Generator;
25  
26  /**
27   * Functional left-fold algorithm against the elements of a {@link Generator}.
28   * Uses the seed object (if supplied) as the initial left-side argument to the {@link BinaryFunction},
29   * then uses the result of that evaluation as the next left-side argument, until the {@link Generator}'s
30   * elements have been expended.
31   *
32   * @param <T> the returned evaluation type.
33   * @version $Revision: 1171154 $ $Date: 2011-09-15 17:58:38 +0200 (Thu, 15 Sep 2011) $
34   */
35  public class FoldLeft<T> implements UnaryFunction<Generator<T>, T>, BinaryFunction<Generator<T>, T, T>, Serializable {
36  
37      /**
38       * serialVersionUID declaration.
39       */
40      private static final long serialVersionUID = 2473542974105910450L;
41  
42      /**
43       * Helper procedure.
44       */
45      private static class FoldLeftHelper<T> implements UnaryProcedure<T> {
46          private final BinaryFunction<? super T, ? super T, ? extends T> function;
47          private T seed;
48          private boolean started;
49  
50          /**
51           * Create a seedless FoldLeftHelper.
52           */
53          public FoldLeftHelper(BinaryFunction<? super T, ? super T, ? extends T> function) {
54              this(null, function);
55          }
56  
57          /**
58           * Create a new FoldLeftHelper.
59           * @param seed initial left-side argument
60           */
61          FoldLeftHelper(T seed, BinaryFunction<? super T, ? super T, ? extends T> function) {
62              this.seed = seed;
63              started = seed != null ? true : false;
64              this.function = function;
65          }
66  
67          /**
68           * {@inheritDoc}
69           */
70          public void run(T obj) {
71              if (!started) {
72                  seed = obj;
73                  started = true;
74              } else {
75                  seed = function.evaluate(seed, obj);
76              }
77          }
78  
79          /**
80           * Get current result.
81           * @return Object
82           */
83          T getResult() {
84              return started ? seed : null;
85          }
86  
87      }
88  
89      private final BinaryFunction<? super T, ? super T, ? extends T> function;
90  
91      /**
92       * Create a new FoldLeft.
93       * @param func {@link BinaryFunction} to apply to each (seed, next)
94       */
95      public FoldLeft(BinaryFunction<? super T, ? super T, ? extends T> func) {
96          this.function = func;
97      }
98  
99      /**
100      * {@inheritDoc}
101      * @param obj {@link Generator} to transform
102      */
103     public final T evaluate(Generator<T> obj) {
104         FoldLeftHelper<T> helper = new FoldLeftHelper<T>(function);
105         obj.run(helper);
106         return helper.getResult();
107     }
108 
109     /**
110      * {@inheritDoc}
111      * @param left {@link Generator} to transform
112      * @param right initial left-side seed object
113      */
114     public final T evaluate(Generator<T> left, T right) {
115         FoldLeftHelper<T> helper = new FoldLeftHelper<T>(right, function);
116         left.run(helper);
117         return helper.getResult();
118     }
119 
120     /**
121      * {@inheritDoc}
122      */
123     public boolean equals(Object obj) {
124         if (obj == this) {
125             return true;
126         }
127         if (!(obj instanceof FoldLeft<?>)) {
128             return false;
129         }
130         return ((FoldLeft<?>) obj).function.equals(function);
131     }
132 
133     /**
134      * {@inheritDoc}
135      */
136     public int hashCode() {
137         return "FoldLeft".hashCode() << 2 ^ function.hashCode();
138     }
139 
140 }