/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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.iterators;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

import org.apache.commons.collections.MapIterator;

/**
 * Abstract class for testing the MapIterator interface.
 * <p>
 * This class provides a framework for testing an implementation of MapIterator.
 * Concrete subclasses must provide the list iterator to be tested.
 * They must also specify certain details of how the list iterator operates by
 * overriding the supportsXxx() methods if necessary.
 * 
 * @since Commons Collections 3.0
 * @version $Revision: 646780 $ $Date: 2008-04-10 13:48:07 +0100 (Thu, 10 Apr 2008) $
 * 
 * @author Stephen Colebourne
 */
public abstract class AbstractTestMapIterator extends AbstractTestIterator {

    /**
     * JUnit constructor.
     * 
     * @param testName  the test class name
     */
    public AbstractTestMapIterator(String testName) {
        super(testName);
    }

    //-----------------------------------------------------------------------
    /**
     * Implement this method to return a map iterator over an empty map.
     * 
     * @return an empty iterator
     */
    public abstract MapIterator makeEmptyMapIterator();

    /**
     * Implement this method to return a map iterator over a map with elements.
     * 
     * @return a full iterator
     */
    public abstract MapIterator makeFullMapIterator();

    /**
     * Implement this method to return the map which contains the same data as the
     * iterator.
     * 
     * @return a full map which can be updated
     */
    public abstract Map getMap();
    
    /**
     * Implement this method to return the confirmed map which contains the same
     * data as the iterator.
     * 
     * @return a full map which can be updated
     */
    public abstract Map getConfirmedMap();
    
    /**
     * Implements the abstract superclass method to return the list iterator.
     * 
     * @return an empty iterator
     */
    public final Iterator makeEmptyIterator() {
        return makeEmptyMapIterator();
    }

    /**
     * Implements the abstract superclass method to return the list iterator.
     * 
     * @return a full iterator
     */
    public final Iterator makeFullIterator() {
        return makeFullMapIterator();
    }

    /**
     * Whether or not we are testing an iterator that supports setValue().
     * Default is true.
     * 
     * @return true if Iterator supports set
     */
    public boolean supportsSetValue() {
        return true;
    }

    /**
     * Whether the get operation on the map structurally modifies the map,
     * such as with LRUMap. Default is false.
     * 
     * @return true if the get method structurally modifies the map
     */
    public boolean isGetStructuralModify() {
        return false;
    }
    
    /**
     * The values to be used in the add and set tests.
     * Default is two strings.
     */
    public Object[] addSetValues() {
        return new Object[] {"A", "B"};
    }

    //-----------------------------------------------------------------------
    /**
     * Test that the empty list iterator contract is correct.
     */
    public void testEmptyMapIterator() {
        if (supportsEmptyIterator() == false) {
            return;
        }

        MapIterator it = makeEmptyMapIterator();
        Map map = getMap();
        assertEquals(false, it.hasNext());
        
        // next() should throw a NoSuchElementException
        try {
            it.next();
            fail();
        } catch (NoSuchElementException ex) {}
        
        // getKey() should throw an IllegalStateException
        try {
            it.getKey();
            fail();
        } catch (IllegalStateException ex) {}
        
        // getValue() should throw an IllegalStateException
        try {
            it.getValue();
            fail();
        } catch (IllegalStateException ex) {}
        
        if (supportsSetValue() == false) {
            // setValue() should throw an UnsupportedOperationException/IllegalStateException
            try {
                it.setValue(addSetValues()[0]);
                fail();
            } catch (UnsupportedOperationException ex) {
            } catch (IllegalStateException ex) {}
        } else {
            // setValue() should throw an IllegalStateException
            try {
                it.setValue(addSetValues()[0]);
                fail();
            } catch (IllegalStateException ex) {}
        }
    }

    //-----------------------------------------------------------------------
    /**
     * Test that the full list iterator contract is correct.
     */
    public void testFullMapIterator() {
        if (supportsFullIterator() == false) {
            return;
        }

        MapIterator it = makeFullMapIterator();
        Map map = getMap();
        assertEquals(true, it.hasNext());
        
        assertEquals(true, it.hasNext());
        Set set = new HashSet();
        while (it.hasNext()) {
            // getKey
            Object key = it.next();
            assertSame("it.next() should equals getKey()", key, it.getKey());
            assertTrue("Key must be in map",  map.containsKey(key));
            assertTrue("Key must be unique", set.add(key));
            
            // getValue
            Object value = it.getValue();
            if (isGetStructuralModify() == false) {
                assertSame("Value must be mapped to key", map.get(key), value);
            }
            assertTrue("Value must be in map",  map.containsValue(value));

            verify();
        }
    }
    
    //-----------------------------------------------------------------------
    public void testMapIteratorSet() {
        if (supportsFullIterator() == false) {
            return;
        }

        Object newValue = addSetValues()[0];
        Object newValue2 = (addSetValues().length == 1 ? addSetValues()[0] : addSetValues()[1]);
        MapIterator it = makeFullMapIterator();
        Map map = getMap();
        Map confirmed = getConfirmedMap();
        assertEquals(true, it.hasNext());
        Object key = it.next();
        Object value = it.getValue();
        
        if (supportsSetValue() == false) {
            try {
                it.setValue(newValue);
                fail();
            } catch (UnsupportedOperationException ex) {}
            return;
        }
        Object old = it.setValue(newValue);
        confirmed.put(key, newValue);
        assertSame("Key must not change after setValue", key, it.getKey());
        assertSame("Value must be changed after setValue", newValue, it.getValue());
        assertSame("setValue must return old value", value, old);
        assertEquals("Map must contain key", true, map.containsKey(key));
        // test against confirmed, as map may contain value twice
        assertEquals("Map must not contain old value", 
            confirmed.containsValue(old), map.containsValue(old));
        assertEquals("Map must contain new value", true, map.containsValue(newValue));
        verify();
        
        it.setValue(newValue);  // same value - should be OK
        confirmed.put(key, newValue);
        assertSame("Key must not change after setValue", key, it.getKey());
        assertSame("Value must be changed after setValue", newValue, it.getValue());
        verify();
        
        it.setValue(newValue2);  // new value
        confirmed.put(key, newValue2);
        assertSame("Key must not change after setValue", key, it.getKey());
        assertSame("Value must be changed after setValue", newValue2, it.getValue());
        verify();
    }

    //-----------------------------------------------------------------------
    public void testRemove() { // override
        MapIterator it = makeFullMapIterator();
        Map map = getMap();
        Map confirmed = getConfirmedMap();
        assertEquals(true, it.hasNext());
        Object key = it.next();
        
        if (supportsRemove() == false) {
            try {
                it.remove();
                fail();
            } catch (UnsupportedOperationException ex) {
            }
            return;
        }
        
        it.remove();
        confirmed.remove(key);
        assertEquals(false, map.containsKey(key));
        verify();
        
        try {
            it.remove();  // second remove fails
        } catch (IllegalStateException ex) {
        }
        verify();
    }

    //-----------------------------------------------------------------------
    public void testMapIteratorSetRemoveSet() {
        if (supportsSetValue() == false || supportsRemove() == false) {
            return;
        }
        Object newValue = addSetValues()[0];
        MapIterator it = makeFullMapIterator();
        Map map = getMap();
        Map confirmed = getConfirmedMap();
        
        assertEquals(true, it.hasNext());
        Object key = it.next();
        
        it.setValue(newValue);
        it.remove();
        confirmed.remove(key);
        verify();
        
        try {
            it.setValue(newValue);
            fail();
        } catch (IllegalStateException ex) {}
        verify();
    }

    //-----------------------------------------------------------------------
    public void testMapIteratorRemoveGetKey() {
        if (supportsRemove() == false) {
            return;
        }
        MapIterator it = makeFullMapIterator();
        Map map = getMap();
        Map confirmed = getConfirmedMap();
        
        assertEquals(true, it.hasNext());
        Object key = it.next();
        
        it.remove();
        confirmed.remove(key);
        verify();
        
        try {
            it.getKey();
            fail();
        } catch (IllegalStateException ex) {}
        verify();
    }

    //-----------------------------------------------------------------------
    public void testMapIteratorRemoveGetValue() {
        if (supportsRemove() == false) {
            return;
        }
        MapIterator it = makeFullMapIterator();
        Map map = getMap();
        Map confirmed = getConfirmedMap();
        
        assertEquals(true, it.hasNext());
        Object key = it.next();
        
        it.remove();
        confirmed.remove(key);
        verify();
        
        try {
            it.getValue();
            fail();
        } catch (IllegalStateException ex) {}
        verify();
    }

}
