/*
 * [GrowingArrayList.java]
 *
 * Summary: Extension to standard ArrayList that automatically grows.
 *
 * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.8+
 *
 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
 *
 * Version History:
 *  1.0 2006-02-21
 */
package com.mindprod.example;

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

import static java.lang.System.*;

/**
 * Extension to standard ArrayList that automatically grows.
 * <p/>
 * If you set the sput index value past the current end rather than
 * throwing an ArrayIndexOutOfMoundsException, the list automatically grows to accommodate.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0 2006-02-21
 * @since 2006-02-21
 */
public final class GrowingArrayList<E> extends ArrayList<E>
    {
    /**
     * true if want the code for the debugging harness.
     */
    private static final boolean DEBUGGING = false;

    /**
     * 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 );
        }

    /**
     * Debug harness.  Demonstrates use of GrowingArrayList
     *
     * @param args not used.
     */
    public static void main( String[] args )
        {
        if ( DEBUGGING )
            {
            List<String> rabbitry = new GrowingArrayList<>( 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 )
                {
                out.println( word );
                }
            }
        }

    /**
     * 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;
        }
    }