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.core.collection;
018
019import java.util.Iterator;
020
021import org.apache.commons.functor.Function;
022import org.apache.commons.lang3.Validate;
023
024/**
025 * Iterator that transforms another Iterator by applying a Function to each returned element.
026 *
027 * @param <E> the function argument type
028 * @param <T> the iterator elements type
029 * @version $Revision: 1508677 $ $Date: 2013-07-31 00:48:02 +0200 (Mi, 31 Jul 2013) $
030 */
031public final class TransformedIterator<E, T> implements Iterator<T> {
032
033    // attributes
034    // ------------------------------------------------------------------------
035
036    /**
037     * The function to apply to each iterator element.
038     */
039    private final Function<? super E, ? extends T> function;
040    /**
041     * The wrapped iterator.
042     */
043    private final Iterator<? extends E> iterator;
044
045    // constructor
046    // ------------------------------------------------------------------------
047    /**
048     * Create a new TransformedIterator.
049     * @param iterator Iterator to decorate
050     * @param function to apply
051     */
052    public TransformedIterator(Iterator<? extends E> iterator, Function<? super E, ? extends T> function) {
053        this.function = Validate.notNull(function, "filtering Function argument was null");
054        this.iterator = Validate.notNull(iterator, "Iterator argument was null");
055    }
056
057    // iterator methods
058    // ------------------------------------------------------------------------
059
060    /**
061     * {@inheritDoc}
062     * @see java.util.Iterator#hasNext()
063     */
064    public boolean hasNext() {
065        return iterator.hasNext();
066    }
067
068    /**
069     * {@inheritDoc}
070     * @see java.util.Iterator#next()
071     */
072    public T next() {
073        return function.evaluate(iterator.next());
074    }
075
076    /**
077     * {@inheritDoc}
078     * @see java.util.Iterator#remove()
079     */
080    public void remove() {
081        iterator.remove();
082    }
083
084    /**
085     * {@inheritDoc}
086     */
087    @Override
088    public boolean equals(Object obj) {
089        if (obj == this) {
090            return true;
091        }
092        if (!(obj instanceof TransformedIterator<?, ?>)) {
093            return false;
094        }
095        TransformedIterator<?, ?> that = (TransformedIterator<?, ?>) obj;
096        return function.equals(that.function) && iterator.equals(that.iterator);
097    }
098
099    /**
100     * {@inheritDoc}
101     */
102    @Override
103    public int hashCode() {
104        int hash = "TransformedIterator".hashCode();
105        hash <<= 2;
106        hash ^= function.hashCode();
107        hash <<= 2;
108        hash ^= iterator.hashCode();
109        return hash;
110    }
111
112    /**
113     * {@inheritDoc}
114     */
115    @Override
116    public String toString() {
117        return "TransformedIterator<" + iterator + "," + function + ">";
118    }
119
120    // class methods
121    // ------------------------------------------------------------------------
122    /**
123     * Get a Transformed Iterator instance.
124     *
125     * @param <E> the function argument type
126     * @param <T> the iterator elements type
127     * @param iter to decorate, if null result is null
128     * @param func transforming function, cannot be null
129     * @return Iterator<T>
130     */
131    public static <E, T> Iterator<T> transform(Iterator<? extends E> iter, Function<? super E, ? extends T> func) {
132        if (null == iter) {
133            return null;
134        }
135        return new TransformedIterator<E, T>(iter, func);
136    }
137
138    /**
139     * Get an Iterator instance that may be transformed.
140     *
141     * @param <E> the iterator elements type
142     * @param iter to decorate, if null result is null
143     * @param func transforming function, if null result is iter
144     * @return Iterator<?>
145     */
146    public static <E> Iterator<?> maybeTransform(Iterator<? extends E> iter, Function<? super E, ?> func) {
147        return null == func ? (null == iter ? null : iter) : new TransformedIterator<E, Object>(iter, func);
148    }
149
150}