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 */
017package org.apache.commons.functor.generator.loop;
018
019import org.apache.commons.functor.Function;
020import org.apache.commons.functor.Procedure;
021import org.apache.commons.functor.generator.Generator;
022import org.apache.commons.lang3.Validate;
023
024/**
025 * Generator that transforms the elements of another Generator.
026 *
027 * @param <I> the type of elements held in the wrapped generator.
028 * @param <E> the type of elements held in this generator.
029 * @version $Revision: 1508677 $ $Date: 2013-07-30 19:48:02 -0300 (Tue, 30 Jul 2013) $
030 */
031public class TransformedGenerator<I, E> extends LoopGenerator<E> {
032
033    /**
034     * The Function to apply to each element.
035     */
036    private final Function<? super I, ? extends E> func;
037
038    /**
039     * Create a new TransformedGenerator.
040     * @param wrapped Generator to transform
041     * @param func Function to apply to each element
042     */
043    // Even though we are passing a Generator<? extends I> to super, and using
044    // it in TransformedGenerator#run, what gets actually passed to the Procedure
045    // is a <? extends E>, returned by func.
046    @SuppressWarnings("unchecked")
047    public TransformedGenerator(Generator<? extends I> wrapped, Function<? super I, ? extends E> func) {
048        super((Generator<? extends E>) Validate.notNull(wrapped, "Generator argument was null"));
049        this.func = Validate.notNull(func, "Function argument was null");
050    }
051
052    /**
053     * {@inheritDoc}
054     */
055    // See comment above in the public constructor
056    @SuppressWarnings("unchecked")
057    public void run(final Procedure<? super E> proc) {
058        ((Generator<? extends I>) getWrappedGenerator()).run(new Procedure<I>() {
059            public void run(I obj) {
060                proc.run(func.evaluate(obj));
061            }
062        });
063    }
064
065    /**
066     * {@inheritDoc}
067     */
068    @Override
069    public boolean equals(Object obj) {
070        if (obj == this) {
071            return true;
072        }
073        if (!(obj instanceof TransformedGenerator<?, ?>)) {
074            return false;
075        }
076        TransformedGenerator<?, ?> other = (TransformedGenerator<?, ?>) obj;
077        return other.getWrappedGenerator().equals(getWrappedGenerator()) && other.func == func;
078    }
079
080    /**
081     * {@inheritDoc}
082     */
083    @Override
084    public int hashCode() {
085        int result = "TransformedGenerator".hashCode();
086        result <<= 2;
087        Generator<?> gen = getWrappedGenerator();
088        result ^= gen.hashCode();
089        result <<= 2;
090        result ^= func.hashCode();
091        return result;
092    }
093}