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.collections4.iterators;
018
019import java.util.Iterator;
020
021import org.apache.commons.collections4.Transformer;
022
023/**
024 * Decorates an iterator such that each element returned is transformed.
025 *
026 * @param <I> the type of the input to the function.
027 * @param <O> the type of the result of the function.
028 * @since 1.0
029 */
030public class TransformIterator<I, O> implements Iterator<O> {
031
032    /** The iterator being used */
033    private Iterator<? extends I> iterator;
034    /** The transformer being used */
035    private Transformer<? super I, ? extends O> transformer;
036
037    /**
038     * Constructs a new {@code TransformIterator} that will not function
039     * until the {@link #setIterator(Iterator) setIterator} and
040     * {@link #setTransformer(Transformer)} methods are invoked.
041     */
042    public TransformIterator() {
043    }
044
045    /**
046     * Constructs a new {@code TransformIterator} that won't transform
047     * elements from the given iterator.
048     *
049     * @param iterator  the iterator to use
050     */
051    public TransformIterator(final Iterator<? extends I> iterator) {
052        this.iterator = iterator;
053    }
054
055    /**
056     * Constructs a new {@code TransformIterator} that will use the
057     * given iterator and transformer.  If the given transformer is null,
058     * then objects will not be transformed.
059     *
060     * @param iterator  the iterator to use
061     * @param transformer  the transformer to use
062     */
063    public TransformIterator(final Iterator<? extends I> iterator,
064                             final Transformer<? super I, ? extends O> transformer) {
065        this.iterator = iterator;
066        this.transformer = transformer;
067    }
068
069    /**
070     * Gets the iterator this iterator is using.
071     *
072     * @return the iterator.
073     */
074    public Iterator<? extends I> getIterator() {
075        return iterator;
076    }
077
078    /**
079     * Gets the transformer this iterator is using.
080     *
081     * @return the transformer.
082     */
083    public Transformer<? super I, ? extends O> getTransformer() {
084        return transformer;
085    }
086
087    @Override
088    public boolean hasNext() {
089        return iterator.hasNext();
090    }
091
092    /**
093     * Gets the next object from the iteration, transforming it using the
094     * current transformer. If the transformer is null, no transformation
095     * occurs and the object from the iterator is returned directly.
096     *
097     * @return the next object
098     * @throws java.util.NoSuchElementException if there are no more elements
099     */
100    @Override
101    public O next() {
102        return transform(iterator.next());
103    }
104
105    @Override
106    public void remove() {
107        iterator.remove();
108    }
109
110    /**
111     * Sets the iterator for this iterator to use.
112     * If iteration has started, this effectively resets the iterator.
113     *
114     * @param iterator  the iterator to use
115     */
116    public void setIterator(final Iterator<? extends I> iterator) {
117        this.iterator = iterator;
118    }
119
120    /**
121     * Sets the transformer this the iterator to use.
122     * A null transformer is a no-op transformer.
123     *
124     * @param transformer  the transformer to use
125     */
126    public void setTransformer(final Transformer<? super I, ? extends O> transformer) {
127        this.transformer = transformer;
128    }
129
130    /**
131     * Transforms the given object using the transformer.
132     * If the transformer is null, the original object is returned as-is.
133     *
134     * @param source  the object to transform
135     * @return the transformed object
136     */
137    protected O transform(final I source) {
138        return transformer.apply(source);
139    }
140}