/*
 * Copyright 1999-2004 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.collections;

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

/**
 * Tests base {@link java.util.List} methods and contracts.
 * <p>
 * To use, simply extend this class, and implement
 * the {@link #makeList} method.
 * <p>
 * If your {@link List} fails one of these tests by design,
 * you may still use this base set of cases.  Simply override the
 * test case (method) your {@link List} fails.
 *
 * @author Rodney Waldhoff
 * @author Paul Jack
 * @version $Id: TestList.java,v 1.13.2.1 2004/05/22 12:14:05 scolebourne Exp $
 */
@SuppressWarnings({"unchecked", "rawtypes"})
public abstract class TestList extends TestCollection {

 


    /**
     *  Return a new, empty {@link List} to be used for testing.
     *
     *  @return an empty list for testing.
     */
    protected abstract List makeEmptyList();


    /**
     *  Return a new, full {@link List} to be used for testing.
     *
     *  @return a full list for testing
     */
    protected List makeFullList() {
        // only works if list supports optional "addAll(Collection)" 
        List list = makeEmptyList();
        list.addAll(Arrays.asList(getFullElements()));
        return list;
    }


    /**
     *  Returns {@link makeEmptyList()}.
     *
     *  @return an empty list to be used for testing
     */
    @Override
    final protected Collection makeCollection() {
        return makeEmptyList();
    }


    /**
     *  Returns {@link makeFullList()}.
     *
     *  @return a full list to be used for testing
     */
    @Override
    final protected Collection makeFullCollection() {
        return makeFullList();
    }



    /**
     * Whether or not we are testing an iterator that can be
     * empty.  Default is true.
     * 
     * @return true if Iterators can be empty
     */
    public boolean supportsEmptyIterator() {
        return true;
    }

    /**
     * Whether or not we are testing an list that allows
     * element set.  Default is true.
     * 
     * @return true if Lists support element set
     */
    public boolean isSetSupported() {
        return true;
    }
    
    
    /**
     *  Returns the {@link collection} field cast to a {@link List}.
     *
     *  @return the collection field as a List
     */
    protected List getList() {
        return (List)collection;
    } 


    /**
     *  Returns the {@link confirmed} field cast to a {@link List}.
     *
     *  @return the confirmed field as a List
     */
    protected List getConfirmedList() {
        return (List)confirmed;
    }


  

      public class TestListIterator extends AbstractTestListIterator {

        @Override
        public Object addSetValue() {
          return TestList.this.getOtherElements()[0];
        }

        @Override
        public boolean supportsRemove() {
          return TestList.this.isRemoveSupported();
        }

        @Override
        public boolean supportsAdd() {
          return TestList.this.isAddSupported();
        }

        @Override
        public boolean supportsSet() {
          return TestList.this.isSetSupported();
        }

        @Override
        public ListIterator makeEmptyListIterator() {
          resetEmpty();
          return ((List) TestList.this.collection).listIterator();
        }

        @Override
        public ListIterator makeFullListIterator() {
          resetFull();
          return ((List) TestList.this.collection).listIterator();
        }

        @Override
        public Object makeObject() {
          return ((List) TestList.this.collection).listIterator();
        }
      }

      /**
       * Tests the read-only bits of {@link List#listIterator()}.
       */
      public void testListListIterator() {
        resetFull();
        forwardTest(getList().listIterator(), 0);
        backwardTest(getList().listIterator(), 0);
      }

      /**
       * Tests the read-only bits of {@link List#listIterator(int)}.
       */
      public void testListListIteratorByIndex() {
        resetFull();
        try {
          getList().listIterator(-1);
        } catch (IndexOutOfBoundsException ex) {
        }
        resetFull();
        try {
          getList().listIterator(getList().size() + 1);
        } catch (IndexOutOfBoundsException ex) {
        }
        resetFull();
        for (int i = 0; i <= confirmed.size(); i++) {
          forwardTest(getList().listIterator(i), i);
          backwardTest(getList().listIterator(i), i);
        }
        resetFull();
        for (int i = 0; i <= confirmed.size(); i++) {
          backwardTest(getList().listIterator(i), i);
        }
      }

      // -----------------------------------------------------------------------
      /**
       * Tests remove on list iterator is correct.
       */
      public void testListListIteratorPreviousRemoveNext() {
        if (isRemoveSupported() == false)
          return;
        resetFull();
        if (collection.size() < 4)
          return;
        ListIterator it = getList().listIterator();
        Object zero = it.next();
        Object one = it.next();
        Object two = it.next();
        Object two2 = it.previous();
        Object one2 = it.previous();
        assertEquals(one, one2);
        assertEquals(two, two2);
        assertEquals(zero, getList().get(0));
        assertEquals(one, getList().get(1));
        assertEquals(two, getList().get(2));
        
        it.remove(); // removed element at index 1 (one)
        assertEquals(zero, getList().get(0));
        assertEquals(two, getList().get(1));
        Object two3 = it.next(); // do next after remove
        assertEquals(two, two3);
        assertEquals(collection.size() > 2, it.hasNext());
        assertEquals(true, it.hasPrevious());
      }

      /**
       * Tests remove on list iterator is correct.
       */
      public void testListListIteratorPreviousRemovePrevious() {
        if (isRemoveSupported() == false)
          return;
        resetFull();
        if (collection.size() < 4)
          return;
        ListIterator it = getList().listIterator();
        Object zero = it.next();
        Object one = it.next();
        Object two = it.next();
        Object two2 = it.previous();
        Object one2 = it.previous();
        assertEquals(one, one2);
        assertEquals(two, two2);
        assertEquals(zero, getList().get(0));
        assertEquals(one, getList().get(1));
        assertEquals(two, getList().get(2));

        it.remove(); // removed element at index 1 (one)
        assertEquals(zero, getList().get(0));
        assertEquals(two, getList().get(1));
        Object zero3 = it.previous(); // do previous after remove
        assertEquals(zero, zero3);
        assertEquals(false, it.hasPrevious());
        assertEquals(collection.size() > 2, it.hasNext());
      }

      /**
       * Tests remove on list iterator is correct.
       */
      public void testListListIteratorNextRemoveNext() {
        if (isRemoveSupported() == false)
          return;
        resetFull();
        if (collection.size() < 4)
          return;
        ListIterator it = getList().listIterator();
        Object zero = it.next();
        Object one = it.next();
        Object two = it.next();
        assertEquals(zero, getList().get(0));
        assertEquals(one, getList().get(1));
        assertEquals(two, getList().get(2));
        Object three = getList().get(3);

        it.remove(); // removed element at index 2 (two)
        assertEquals(zero, getList().get(0));
        assertEquals(one, getList().get(1));
        Object three2 = it.next(); // do next after remove
        assertEquals(three, three2);
        assertEquals(collection.size() > 3, it.hasNext());
        assertEquals(true, it.hasPrevious());
      }

      /**
       * Tests remove on list iterator is correct.
       */
      public void testListListIteratorNextRemovePrevious() {
        if (isRemoveSupported() == false)
          return;
        resetFull();
        if (collection.size() < 4)
          return;
        ListIterator it = getList().listIterator();
        Object zero = it.next();
        Object one = it.next();
        Object two = it.next();
        assertEquals(zero, getList().get(0));
        assertEquals(one, getList().get(1));
        assertEquals(two, getList().get(2));

        it.remove(); // removed element at index 2 (two)
        assertEquals(zero, getList().get(0));
        assertEquals(one, getList().get(1));
        Object one2 = it.previous(); // do previous after remove
        assertEquals(one, one2);
        assertEquals(true, it.hasNext());
        assertEquals(true, it.hasPrevious());
      }

      // -----------------------------------------------------------------------
      /**
       * Traverses to the end of the given iterator.
       * 
       * @param iter the iterator to traverse
       * @param i the starting index
       */
      private void forwardTest(ListIterator iter, int i) {
        List list = getList();
        int max = getFullElements().length;

        while (i < max) {
          assertTrue("Iterator should have next", iter.hasNext());
          assertEquals("Iterator.nextIndex should work", iter.nextIndex(), i);
          assertEquals("Iterator.previousIndex should work", iter.previousIndex(),
              i - 1);
          Object o = iter.next();
          assertEquals("Iterator returned correct element f", list.get(i), o);
          i++;
        }

        assertTrue("Iterator shouldn't have next", !iter.hasNext());
        assertEquals("nextIndex should be size", iter.nextIndex(), max);
        assertEquals("previousIndex should be size - 1", iter.previousIndex(),
            max - 1);

        try {
          iter.next();
          fail("Exhausted iterator should raise NoSuchElement");
        } catch (NoSuchElementException e) {
          // expected
        }
      }

      /**
       * Traverses to the beginning of the given iterator.
       * 
       * @param iter the iterator to traverse
       * @param i the starting index
       */
      private void backwardTest(ListIterator iter, int i) {
        List list = getList();

        while (i > 0) {
          assertTrue("Iterator should have previous, i:" + i, iter.hasPrevious());
          assertEquals("Iterator.nextIndex should work, i:" + i, iter.nextIndex(),
              i);
          assertEquals("Iterator.previousIndex should work, i:" + i,
              iter.previousIndex(), i - 1);
          Object o = iter.previous();
          assertEquals("Iterator returned correct element b", list.get(i - 1), o);
          i--;
        }

        assertTrue("Iterator shouldn't have previous", !iter.hasPrevious());
        int nextIndex = iter.nextIndex();
    assertEquals("nextIndex should be 0, actual value: " + nextIndex, 0, nextIndex);
        int prevIndex = iter.previousIndex();
    assertEquals("previousIndex should be -1, actual value: " + prevIndex, -1, prevIndex);

        try {
          iter.previous();
          fail("Exhausted iterator should raise NoSuchElement");
        } catch (NoSuchElementException e) {
          // expected
        }

      }

      /**
       * Tests the {@link ListIterator#add(Object)} method of the list iterator.
       */
      public void testListIteratorAdd() {
        if (!isAddSupported())
          return;

        resetEmpty();
        List list1 = getList();
        List list2 = getConfirmedList();

        Object[] elements = getFullElements();
        ListIterator iter1 = list1.listIterator();
        ListIterator iter2 = list2.listIterator();

        for (int i = 0; i < elements.length; i++) {
          iter1.add(elements[i]);
          iter2.add(elements[i]);
          verify();
        }

        resetFull();
        iter1 = getList().listIterator();
        iter2 = getConfirmedList().listIterator();
        for (int i = 0; i < elements.length; i++) {
          iter1.next();
          iter2.next();
          iter1.add(elements[i]);
          iter2.add(elements[i]);
          verify();
        }
      }

      /**
       * Tests the {@link ListIterator#set(Object)} method of the list iterator.
       */
      public void testListIteratorSet() {
        if (!isSetSupported())
          return;

        Object[] elements = getFullElements();

        resetFull();
        ListIterator iter1 = getList().listIterator();
        ListIterator iter2 = getConfirmedList().listIterator();
        for (int i = 0; i < elements.length; i++) {
          iter1.next();
          iter2.next();
          iter1.set(elements[i]);
          iter2.set(elements[i]);
          verify();
        }
      }

      
      
      
    /**
     *  Tests {@link List#add(int,Object)}.
     */
    public void testListAddByIndex() {
        if (!isAddSupported()) return;

        Object element = getOtherElements()[0];
        int max = getFullElements().length;

        for (int i = 0; i <= max; i++) {
            resetFull();
            ((List)collection).add(i, element);
            ((List)confirmed).add(i, element);
            verify();
        }
    }


    /**
     *  Tests {@link List#equals(Object)}.
     */
    public void testListEquals() {
        resetEmpty();
        List list = getList();
        assertTrue("Empty lists should be equal", list.equals(confirmed));
        verify();
        assertTrue("Empty list should equal self", list.equals(list));
        verify();

        List list2 = Arrays.asList(getFullElements());
        assertTrue("Empty list shouldn't equal full", !list.equals(list2));
        verify();

        list2 = Arrays.asList(getOtherElements());
        assertTrue("Empty list shouldn't equal other", !list.equals(list2));
        verify();

        resetFull();
        list = getList();
        assertTrue("Full lists should be equal", list.equals(confirmed));
        verify();
        assertTrue("Full list should equal self", list.equals(list));
        verify();

        list2 = makeEmptyList();
        assertTrue("Full list shouldn't equal empty", !list.equals(list2));
        verify();

        list2 = Arrays.asList(getOtherElements());
        assertTrue("Full list shouldn't equal other", !list.equals(list2));
        verify();

        list2 = Arrays.asList(getFullElements());
        Collections.reverse(list2);
        assertTrue("Full list shouldn't equal full list with same elements" +
          " but different order", !list.equals(list2));
        verify();

        assertTrue("List shouldn't equal String", !list.equals(""));
        verify();

        final List listForC = Arrays.asList(getFullElements());
        Collection c = new AbstractCollection() {
            @Override
            public int size() {
                return listForC.size();
            }

            @Override
            public Iterator iterator() {
                return listForC.iterator();
            }
        };

        assertTrue("List shouldn't equal nonlist with same elements " +
          " in same order", !list.equals(c));
        verify();
    }


    /**
     *  Tests {@link List#hashCode()}.
     */
    public void testListHashCode() {
        resetEmpty();
        int hash1 = collection.hashCode();
        int hash2 = confirmed.hashCode();
        assertEquals("Empty lists should have equal hashCodes", hash1, hash2);
        verify();

        resetFull();
        hash1 = collection.hashCode();
        hash2 = confirmed.hashCode();
        assertEquals("Full lists should have equal hashCodes", hash1, hash2);
        verify();
    }


    /**
     *  Tests {@link List#get(int)}.
     */
    public void testListGetByIndex() {
        resetFull();
        List list = getList();
        Object[] elements = getFullElements();
        for (int i = 0; i < elements.length; i++) {
            assertEquals("List should contain correct elements", 
              elements[i], list.get(i));
            verify();
        }
    }


     
    /**
     *  Tests {@link List#indexOf()}.
     */
    public void testListIndexOf() {
        resetFull();
        List list1 = getList();
        List list2 = getConfirmedList();

        Iterator iterator = list2.iterator();
        while (iterator.hasNext()) {
            Object element = iterator.next();
            assertEquals("indexOf should return correct result", 
              list1.indexOf(element), list2.indexOf(element));            
            verify();
        }

        Object[] other = getOtherElements();
        for (int i = 0; i < other.length; i++) {
      assertEquals("indexOf should return -1 for nonexistent element", -1, list1.indexOf(other[i]));
            verify();
        }
    }


    /**
     *  Tests {@link List#lastIndexOf()}.
     */
    public void testListLastIndexOf() {
        resetFull();
        List list1 = getList();
        List list2 = getConfirmedList();

        Iterator iterator = list2.iterator();
        while (iterator.hasNext()) {
            Object element = iterator.next();
            assertEquals("lastIndexOf should return correct result",
              list1.lastIndexOf(element), list2.lastIndexOf(element));
            verify();
        }

        Object[] other = getOtherElements();
        for (int i = 0; i < other.length; i++) {
      assertEquals(
          "lastIndexOf should return -1 for nonexistent " + "element",
          -1,
          list1.lastIndexOf(other[i]));
            verify();
        }
    }


     

    /**
     *  Tests {@link List#remove(int)}.
     */
    public void testListRemoveByIndex() {
        if (!isRemoveSupported()) return;

        int max = getFullElements().length;
        for (int i = 0; i < max; i++) {
            resetFull();
            Object o1 = ((List)collection).remove(i);
            Object o2 = ((List)confirmed).remove(i);
            assertEquals("remove should return correct element", o1, o2);
            verify();
        }
    }
 
 
  
 
   
   
    


    /**
     *  Returns an empty {@link ArrayList}.
     */
    @Override
    protected Collection makeConfirmedCollection() {
        ArrayList list = new ArrayList();
        return list;
    }


    /**
     *  Returns a full {@link ArrayList}.
     */
    @Override
    protected Collection makeConfirmedFullCollection() {
        ArrayList list = new ArrayList();
        list.addAll(Arrays.asList(getFullElements()));
        return list;
    }


    /**
     *  Verifies that the test list implementation matches the confirmed list
     *  implementation.
     */
    @Override
    protected void verify() {
        super.verify();

        List list1 = getList();
        List list2 = getConfirmedList();

        assertEquals("List should equal confirmed", list1, list2);
        assertEquals("Confirmed should equal list", list2, list1);

        assertEquals("Hash codes should be equal", 
          list1.hashCode(), list2.hashCode());

        int i = 0;
        Iterator iterator1 = list1.iterator();
        Iterator iterator2 = list2.iterator();
        Object[] array = list1.toArray();
        while (iterator2.hasNext()) {
            assertTrue("List iterator should have next", iterator1.hasNext());
            Object o1 = iterator1.next();
            Object o2 = iterator2.next();
            assertEquals("Iterator elements should be equal", o1, o2);
            o2 = list1.get(i);
            assertEquals("get should return correct element", o1, o2);
            o2 = array[i];
            assertEquals("toArray should have correct element", o1, o2);
            i++;
        }
    }

    
 

}
