/*
 * 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.myfaces.test.mock;

import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;


/**
 * Helper Map implementation for use with different Attribute Maps.
 *
 * @author Anton Koinov (latest modification by $Author: grantsmith $)
 * @version $Revision: 472618 $ $Date: 2006-11-08 15:06:54 -0500 (Mié, 08 Nov 2006) $
 */
abstract class _AbstractAttributeMap
    extends AbstractMap
{
    private Set              _keySet;
    private Collection       _values;
    private Set              _entrySet;

    public void clear()
    {
        List names = new ArrayList();
        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
        {
            names.add(e.nextElement());
        }

        for (Iterator it = names.iterator(); it.hasNext();)
        {
            removeAttribute((String) it.next());
        }
    }

    public boolean containsKey(Object key)
    {
        return getAttribute(key.toString()) != null;
    }

    public boolean containsValue(Object findValue)
    {
        if (findValue == null)
        {
            return false;
        }

        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
        {
            Object value = getAttribute((String) e.nextElement());
            if (findValue.equals(value))
            {
                return true;
            }
        }

        return false;
    }

    public Set entrySet()
    {
        return (_entrySet != null) ? _entrySet : (_entrySet = new EntrySet());
    }

    public Object get(Object key)
    {
        return getAttribute(key.toString());
    }

    public boolean isEmpty()
    {
        return !getAttributeNames().hasMoreElements();
    }

    public Set keySet()
    {
        return (_keySet != null) ? _keySet : (_keySet = new KeySet());
    }

    public Object put(Object key, Object value)
    {
        String key_ = key.toString();
        Object retval = getAttribute(key_);
        setAttribute(key_, value);
        return retval;
    }

    public void putAll(Map t)
    {
        for (Iterator it = t.entrySet().iterator(); it.hasNext();)
        {
            Entry entry = (Entry) it.next();
            setAttribute(entry.getKey().toString(), entry.getValue());
        }
    }

    public Object remove(Object key)
    {
        String key_ = key.toString();
        Object retval = getAttribute(key_);
        removeAttribute(key_);
        return retval;
    }

    public int size()
    {
        int size = 0;
        for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
        {
            size++;
            e.nextElement();
        }
        return size;
    }

    public Collection values()
    {
        return (_values != null) ? _values : (_values = new Values());
    }


    abstract protected Object getAttribute(String key);

    abstract protected void setAttribute(String key, Object value);

    abstract protected void removeAttribute(String key);

    abstract protected Enumeration getAttributeNames();


    private class KeySet extends AbstractSet
    {
        public Iterator iterator()
        {
            return new KeyIterator();
        }

        public boolean isEmpty()
        {
            return _AbstractAttributeMap.this.isEmpty();
        }

        public int size()
        {
            return _AbstractAttributeMap.this.size();
        }

        public boolean contains(Object o)
        {
            return _AbstractAttributeMap.this.containsKey(o);
        }

        public boolean remove(Object o)
        {
            return _AbstractAttributeMap.this.remove(o) != null;
        }

        public void clear()
        {
            _AbstractAttributeMap.this.clear();
        }
    }

    private class KeyIterator
        implements Iterator
    {
        protected final Enumeration _e = getAttributeNames();
        protected Object            _currentKey;

        public void remove()
        {
            // remove() may cause ConcurrentModificationException.
            // We could throw an exception here, but not throwing an exception
            //   allows one call to remove() to succeed
            if (_currentKey == null)
            {
                throw new NoSuchElementException(
                    "You must call next() at least once");
            }
            _AbstractAttributeMap.this.remove(_currentKey);
        }

        public boolean hasNext()
        {
            return _e.hasMoreElements();
        }

        public Object next()
        {
            return _currentKey = _e.nextElement();
        }
    }

    private class Values extends KeySet
    {
        public Iterator iterator()
        {
            return new ValuesIterator();
        }

        public boolean contains(Object o)
        {
            return _AbstractAttributeMap.this.containsValue(o);
        }

        public boolean remove(Object o)
        {
            if (o == null)
            {
                return false;
            }

            for (Iterator it = iterator(); it.hasNext();)
            {
                if (o.equals(it.next()))
                {
                    it.remove();
                    return true;
                }
            }

            return false;
        }
    }

    private class ValuesIterator extends KeyIterator
    {
        public Object next()
        {
            super.next();
            return _AbstractAttributeMap.this.get(_currentKey);
        }
    }

    private class EntrySet extends KeySet
    {
        public Iterator iterator() {
            return new EntryIterator();
        }

        public boolean contains(Object o) {
            if (!(o instanceof Entry))
            {
                return false;
            }

            Entry entry = (Entry) o;
            Object key = entry.getKey();
            Object value = entry.getValue();
            if (key == null || value == null)
            {
                return false;
            }

            return value.equals(_AbstractAttributeMap.this.get(key));
        }

        public boolean remove(Object o) {
            if (!(o instanceof Entry))
            {
                return false;
            }

            Entry entry = (Entry) o;
            Object key = entry.getKey();
            Object value = entry.getValue();
            if (key == null || value == null
                || !value.equals(_AbstractAttributeMap.this.get(key)))
            {
                return false;
            }

            return _AbstractAttributeMap.this.remove(((Entry) o).getKey()) != null;
        }
    }

    /**
     * Not very efficient since it generates a new instance of <code>Entry</code>
     * for each element and still internaly uses the <code>KeyIterator</code>.
     * It is more efficient to use the <code>KeyIterator</code> directly.
     */
    private class EntryIterator extends KeyIterator
    {
        public Object next()
        {
            super.next();
            // Must create new Entry every time--value of the entry must stay
            // linked to the same attribute name
            return new EntrySetEntry(_currentKey);
        }
    }

    private class EntrySetEntry implements Entry
    {
        private final Object _currentKey;

        public EntrySetEntry(Object currentKey)
        {
            _currentKey = currentKey;
        }

        public Object getKey()
        {
            return _currentKey;
        }

        public Object getValue()
        {
            return _AbstractAttributeMap.this.get(_currentKey);
        }

        public Object setValue(Object value)
        {
            return _AbstractAttributeMap.this.put(_currentKey, value);
        }

        public int hashCode() {
            return _currentKey == null ? 0 : _currentKey.hashCode();
        }

        public boolean equals(Object obj) {
            if (!(obj instanceof EntrySetEntry))
                return false;
            return _currentKey != null && _currentKey.equals(obj);
        }
    }
}
