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 }