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