001package com.identityworksllc.iiq.common.iterators;
002
003import java.util.Collections;
004import java.util.Iterator;
005import java.util.List;
006import java.util.concurrent.atomic.AtomicInteger;
007
008/**
009 * An indexing class for associating items in a list with their index in the list
010 *
011 * @param <T> The indexed type
012 */
013public final class Index<T> {
014    /**
015     * Implements an equivalent to Javascript's eachWithIndex. This is a shortcut
016     * to {@link IndexingIterator}. If the input is null, a constant empty iterator
017     * is returned.
018     *
019     * @param iterator The input list to iterate over
020     * @param <In> The type of the values in the list
021     * @return An indexed iterator over the given child iterator
022     */
023    public static <In> Iterator<Index<In>> with(Iterator<? extends In> iterator) {
024        if (iterator == null) {
025            return Collections.emptyIterator();
026        }
027
028        return new IndexingIterator<>(iterator);
029    }
030
031    /**
032     * Implements an equivalent to Javascript's eachWithIndex. If the input is
033     * null or empty, a constant empty Iterable is returned.
034     *
035     * The output of this method is not itself a List.
036     *
037     * @param iterable The input list to iterate over
038     * @param <In> The type of the values in the list
039     * @return An indexed iterator over the given list
040     */
041    public static <In> Iterable<Index<In>> with(List<? extends In> iterable) {
042        if (iterable == null || iterable.isEmpty()) {
043            // Why does this syntax work? It's because the compiler is just looking for
044            // something to substitute in as Iterable.iterator(), and this will
045            // do just fine.
046            return Collections::emptyIterator;
047        }
048
049        return () -> {
050            final Iterator<? extends In> wrappedIterator = iterable.iterator();
051            return with(wrappedIterator);
052        };
053    }
054
055    /**
056     * The integer index, starting with 0
057     */
058    private final int index;
059
060    /**
061     * The value at this index
062     */
063    private final T value;
064
065    /**
066     * Create a new indexed value
067     *
068     * @param value The value
069     * @param index The index
070     */
071    public Index(T value, int index) {
072        this.value = value;
073        this.index = index;
074    }
075
076    /**
077     * Gets the integer index value
078     *
079     * @return The integer index value
080     */
081    public int getIndex() {
082        return index;
083    }
084
085    /**
086     * The value at that position in the list
087     *
088     * @return The value at the list position
089     */
090    public T getValue() {
091        return value;
092    }
093}