001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.commons.collections4.iterators;
019
020import java.util.Iterator;
021
022import org.apache.commons.collections4.ArrayStack;
023
024/**
025 * Decorates an iterator to support pushback of elements.
026 * <p>
027 * The decorator stores the pushed back elements in a LIFO manner: the last element
028 * that has been pushed back, will be returned as the next element in a call to {@link #next()}.
029 * <p>
030 * The decorator does not support the removal operation. Any call to {@link #remove()} will
031 * result in an {@link UnsupportedOperationException}.
032 *
033 * @since 4.0
034 * @version $Id: PushbackIterator.html 972421 2015-11-14 20:00:04Z tn $
035 */
036@SuppressWarnings("deprecation") // replace ArrayStack with ArrayDeque when moving to Java 6
037public class PushbackIterator<E> implements Iterator<E> {
038
039    /** The iterator being decorated. */
040    private final Iterator<? extends E> iterator;
041
042    /** The LIFO queue containing the pushed back items. */
043    private ArrayStack<E> items = new ArrayStack<E>();
044
045    //-----------------------------------------------------------------------
046    /**
047     * Decorates the specified iterator to support one-element lookahead.
048     * <p>
049     * If the iterator is already a {@link PeekingIterator} it is returned directly.
050     *
051     * @param <E>  the element type
052     * @param iterator  the iterator to decorate
053     * @return a new peeking iterator
054     * @throws IllegalArgumentException if the iterator is null
055     */
056    public static <E> PushbackIterator<E> pushbackIterator(final Iterator<? extends E> iterator) {
057        if (iterator == null) {
058            throw new IllegalArgumentException("Iterator must not be null");
059        }
060        if (iterator instanceof PushbackIterator<?>) {
061            @SuppressWarnings("unchecked") // safe cast
062            final PushbackIterator<E> it = (PushbackIterator<E>) iterator;
063            return it;
064        }
065        return new PushbackIterator<E>(iterator);
066    }
067
068    //-----------------------------------------------------------------------
069
070    /**
071     * Constructor.
072     *
073     * @param iterator  the iterator to decorate
074     */
075    public PushbackIterator(final Iterator<? extends E> iterator) {
076        super();
077        this.iterator = iterator;
078    }
079
080    /**
081     * Push back the given element to the iterator.
082     * <p>
083     * Calling {@link #next()} immediately afterwards will return exactly this element.
084     *
085     * @param item  the element to push back to the iterator
086     */
087    public void pushback(final E item) {
088        items.push(item);
089    }
090
091    public boolean hasNext() {
092        return !items.isEmpty() ? true : iterator.hasNext();
093    }
094
095    public E next() {
096        return !items.isEmpty() ? items.pop() : iterator.next();
097    }
098
099    /**
100     * This iterator will always throw an {@link UnsupportedOperationException}.
101     *
102     * @throws UnsupportedOperationException always
103     */
104    public void remove() {
105        throw new UnsupportedOperationException();
106    }
107
108}