package com.mindprod.example;

import java.util.ArrayList;
import java.util.List;

/**
 * Extension to standard ArrayList that automatically grows when you set a value past the current end rather than
 * throwing an ArrayIndexOutOfMoundsException.
 * <p/>
 * composed with IntelliJ IDEA
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0, 2006-02-21
 */
public final class GrowingArrayList<E> extends ArrayList<E>
    {
// ------------------------------ FIELDS ------------------------------

    /**
     * true if want the code for the debugging harness.
     */
    private static final boolean DEBUGGING = true;

    // -------------------------- PUBLIC INSTANCE  METHODS --------------------------
    /**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param initialCapacity the initial capacity of the list.
     * @throws IllegalArgumentException if the specified initial capacity is negative
     */
    @SuppressWarnings( { "SameParameterValue", "WeakerAccess" } )
    public GrowingArrayList( int initialCapacity )
        {
        super( initialCapacity );
        }

    /**
     * Replaces the element at the specified position in this list with the specified element. Unlike ordinary
     * ArrayList.set the array automatically grows if index >= size.
     *
     * @param index   index of element to replace.
     * @param element element to be stored at the specified position.
     * @return the element previously at the specified position.
     * @throws IndexOutOfBoundsException if index out of range <tt>( index &lt; 0 )</tt>.
     */
    public E set( int index, E element )
        {
        int size = this.size();
        if ( index < size )
            {
            return super.set( index, element );
            }
        // Unfortunately for us:
        // super.set element must exist already.
        // add increses size by one, no more.
        // There is no setSize method.
        // setCapacity has no effect on the array size.
        // so we must painfully grow the array one element at a time.
        int dummiesRequired = index - size;
        for ( ; dummiesRequired > 0; dummiesRequired-- )
            {
            super.add( null );
            }
        super.add( element );
        return null;
        }

// --------------------------- main() method ---------------------------

    /**
     * Debug harness.  Demonstrates use of GrowingArrayList
     *
     * @param args not used.
     */
    public static void main( String[] args )
        {
        if ( DEBUGGING )
            {
            List<String> rabbitry = new GrowingArrayList<String>( 10 );
            rabbitry.add( "rabbit" );
            rabbitry.add( "dog" );
            rabbitry.add( "buck" );
            rabbitry.set( 1, "doe" );
            // a normal ArrayList would give an IndexOfOfrangeException here,
            // GrowingArrayList grows as needed.
            rabbitry.set( 5, "hare" );
            /*
            prints:
              rabbit
              doe
              buck
              null
              null
              hare
            */
            for ( String word : rabbitry )
                {
                System.out.println( word );
                }
            }
        }
    }