001package com.identityworksllc.iiq.common.iterators;
002
003import java.util.Iterator;
004import java.util.Objects;
005import java.util.concurrent.atomic.AtomicInteger;
006
007/**
008 * An iterator that keeps track of its index, allowing you to get the current
009 * element count.
010 *
011 * @param <In> The input iterator type
012 */
013public class IndexingIterator<In> implements Iterator<Index<In>> {
014    /**
015     * The index counter
016     */
017    private final AtomicInteger index;
018
019    /**
020     * The input iterator
021     */
022    private final Iterator<? extends In> input;
023
024    /**
025     * Wrapper constructor
026     * @param input The input iterator
027     */
028    public IndexingIterator(Iterator<? extends In> input) {
029        this.input = Objects.requireNonNull(input);
030        this.index = new AtomicInteger(-1);
031    }
032
033    /**
034     * @see Iterator#hasNext()
035     */
036    @Override
037    public boolean hasNext() {
038        return input.hasNext();
039    }
040
041    /**
042     * @see Iterator#next()
043     */
044    @Override
045    public Index<In> next() {
046        return new Index<>(input.next(), index.incrementAndGet());
047    }
048
049    /**
050     * Removes the current item from the list and decrements the index. The
051     * next item returned will have the same index as the previous one. If
052     * the wrapped iterator does not support removals, this method will throw
053     * an appropriate exception without decrementing the counter.
054     */
055    @Override
056    public void remove() {
057        input.remove();
058        index.decrementAndGet();
059    }
060}