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 021 import org.apache.commons.functor.BinaryFunction; 022 import org.apache.commons.functor.UnaryFunction; 023 import org.apache.commons.functor.UnaryProcedure; 024 import org.apache.commons.functor.generator.Generator; 025 026 /** 027 * Functional left-fold algorithm against the elements of a {@link Generator}. 028 * Uses the seed object (if supplied) as the initial left-side argument to the {@link BinaryFunction}, 029 * then uses the result of that evaluation as the next left-side argument, until the {@link Generator}'s 030 * elements have been expended. 031 * 032 * @param <T> the returned evaluation type. 033 * @version $Revision: 1171154 $ $Date: 2011-09-15 17:58:38 +0200 (Thu, 15 Sep 2011) $ 034 */ 035 public class FoldLeft<T> implements UnaryFunction<Generator<T>, T>, BinaryFunction<Generator<T>, T, T>, Serializable { 036 037 /** 038 * serialVersionUID declaration. 039 */ 040 private static final long serialVersionUID = 2473542974105910450L; 041 042 /** 043 * Helper procedure. 044 */ 045 private static class FoldLeftHelper<T> implements UnaryProcedure<T> { 046 private final BinaryFunction<? super T, ? super T, ? extends T> function; 047 private T seed; 048 private boolean started; 049 050 /** 051 * Create a seedless FoldLeftHelper. 052 */ 053 public FoldLeftHelper(BinaryFunction<? super T, ? super T, ? extends T> function) { 054 this(null, function); 055 } 056 057 /** 058 * Create a new FoldLeftHelper. 059 * @param seed initial left-side argument 060 */ 061 FoldLeftHelper(T seed, BinaryFunction<? super T, ? super T, ? extends T> function) { 062 this.seed = seed; 063 started = seed != null ? true : false; 064 this.function = function; 065 } 066 067 /** 068 * {@inheritDoc} 069 */ 070 public void run(T obj) { 071 if (!started) { 072 seed = obj; 073 started = true; 074 } else { 075 seed = function.evaluate(seed, obj); 076 } 077 } 078 079 /** 080 * Get current result. 081 * @return Object 082 */ 083 T getResult() { 084 return started ? seed : null; 085 } 086 087 } 088 089 private final BinaryFunction<? super T, ? super T, ? extends T> function; 090 091 /** 092 * Create a new FoldLeft. 093 * @param func {@link BinaryFunction} to apply to each (seed, next) 094 */ 095 public FoldLeft(BinaryFunction<? super T, ? super T, ? extends T> func) { 096 this.function = func; 097 } 098 099 /** 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 }