blob: ef5aecbad67a7a5fa91ef9a69b50ab5bf5383798 [file] [log] [blame]
/*
* 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.Collection;
import java.util.Collections;
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: jakobk $)
* @version $Revision: 979229 $ $Date: 2010-07-26 12:26:53 +0200 (Mo, 26 Jul 2010) $
* @since 1.0.0
*/
abstract class _AbstractAttributeMap<V> extends AbstractMap<String, V>
{
private Set<String> _keySet;
private Collection<V> _values;
private Set<Entry<String, V>> _entrySet;
@Override
public void clear()
{
final List<String> names = Collections.list(getAttributeNames());
for (String name : names)
{
removeAttribute(name);
}
}
@Override
public final boolean containsKey(final Object key)
{
return getAttribute(key.toString()) != null;
}
@Override
public boolean containsValue(final Object findValue)
{
if (findValue == null)
{
return false;
}
for (final Enumeration<String> e = getAttributeNames(); e
.hasMoreElements();)
{
final Object value = getAttribute(e.nextElement());
if (findValue.equals(value))
{
return true;
}
}
return false;
}
@Override
public Set<Entry<String, V>> entrySet()
{
if (_entrySet == null)
{
_entrySet = new EntrySet();
}
return _entrySet;
}
@Override
public V get(final Object key)
{
return getAttribute(key.toString());
}
@Override
public boolean isEmpty()
{
return !getAttributeNames().hasMoreElements();
}
@Override
public Set<String> keySet()
{
if (_keySet == null)
{
_keySet = new KeySet();
}
return _keySet;
}
@Override
public final V put(final String key, final V value)
{
final V retval = getAttribute(key);
setAttribute(key, value);
return retval;
}
@Override
public void putAll(final Map<? extends String, ? extends V> t)
{
for (final Entry<? extends String, ? extends V> entry : t.entrySet())
{
setAttribute(entry.getKey(), entry.getValue());
}
}
@Override
public final V remove(final Object key)
{
final String tempKey = key.toString();
final V retval = getAttribute(tempKey);
removeAttribute(tempKey);
return retval;
}
@Override
public int size()
{
int size = 0;
for (final Enumeration<String> e = getAttributeNames(); e
.hasMoreElements();)
{
size++;
e.nextElement();
}
return size;
}
@Override
public Collection<V> values()
{
if(_values == null)
{
_values = new Values();
}
return _values;
}
abstract protected V getAttribute(String key);
abstract protected void setAttribute(String key, V value);
abstract protected void removeAttribute(String key);
abstract protected Enumeration<String> getAttributeNames();
private abstract class AbstractAttributeSet<E> extends AbstractSet<E>
{
@Override
public boolean isEmpty()
{
return _AbstractAttributeMap.this.isEmpty();
}
@Override
public int size()
{
return _AbstractAttributeMap.this.size();
}
@Override
public void clear()
{
_AbstractAttributeMap.this.clear();
}
}
private final class KeySet extends AbstractAttributeSet<String>
{
@Override
public Iterator<String> iterator()
{
return new KeyIterator();
}
@Override
public boolean contains(final Object o)
{
return _AbstractAttributeMap.this.containsKey(o);
}
@Override
public boolean remove(final Object o)
{
return _AbstractAttributeMap.this.remove(o) != null;
}
}
private abstract class AbstractAttributeIterator<E> implements Iterator<E>
{
// We use a copied version of the Enumeration from getAttributeNames()
// here, because directly using it might cause a ConcurrentModificationException
// when performing remove(). Note that we can do this since the Enumeration
// from getAttributeNames() will contain exactly the attribute names from the time
// getAttributeNames() was called and it will not be updated if attributes are
// removed or added.
protected final Iterator<String> _i = Collections.list(
getAttributeNames()).iterator();
protected String _currentKey;
public void remove()
{
if (_currentKey == null)
{
throw new NoSuchElementException(
"You must call next() at least once");
}
_AbstractAttributeMap.this.remove(_currentKey);
}
public boolean hasNext()
{
return _i.hasNext();
}
public E next()
{
_currentKey = _i.next();
return getValue(_currentKey);
}
protected abstract E getValue(String attributeName);
}
private final class KeyIterator extends AbstractAttributeIterator<String>
{
@Override
protected String getValue(final String attributeName)
{
return attributeName;
}
}
private class Values extends AbstractAttributeSet<V>
{
@Override
public Iterator<V> iterator()
{
return new ValuesIterator();
}
@Override
public boolean contains(final Object o)
{
if (o == null)
{
return false;
}
for (final Iterator<V> it = iterator(); it.hasNext();)
{
if (o.equals(it.next()))
{
return true;
}
}
return false;
}
@Override
public boolean remove(final Object o)
{
if (o == null)
{
return false;
}
for (final Iterator<V> it = iterator(); it.hasNext();)
{
if (o.equals(it.next()))
{
it.remove();
return true;
}
}
return false;
}
}
private class ValuesIterator extends AbstractAttributeIterator<V>
{
@Override
protected V getValue(final String attributeName)
{
return _AbstractAttributeMap.this.get(attributeName);
}
}
private final class EntrySet extends AbstractAttributeSet<Entry<String, V>>
{
@Override
public Iterator<Entry<String, V>> iterator()
{
return new EntryIterator();
}
@SuppressWarnings("unchecked")
@Override
public boolean contains(final Object o)
{
if (!(o instanceof Entry))
{
return false;
}
final Entry<String, V> entry = (Entry<String, V>) o;
final Object key = entry.getKey();
final Object value = entry.getValue();
if (key == null || value == null)
{
return false;
}
return value.equals(_AbstractAttributeMap.this.get(key));
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(final Object o)
{
if (!(o instanceof Entry))
{
return false;
}
final Entry<String, V> entry = (Entry<String, V>) o;
final Object key = entry.getKey();
final Object value = entry.getValue();
if (key == null || value == null
|| !value.equals(_AbstractAttributeMap.this.get(key)))
{
return false;
}
return _AbstractAttributeMap.this.remove(((Entry<String, V>) 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 final class EntryIterator extends
AbstractAttributeIterator<Entry<String, V>>
{
@Override
protected Entry<String, V> getValue(final String attributeName)
{
// Must create new Entry every time--value of the entry must stay
// linked to the same attribute name
return new EntrySetEntry(attributeName);
}
}
private final class EntrySetEntry implements Entry<String, V>
{
private final String _currentKey;
public EntrySetEntry(final String currentKey)
{
_currentKey = currentKey;
}
public String getKey()
{
return _currentKey;
}
public V getValue()
{
return _AbstractAttributeMap.this.get(_currentKey);
}
public V setValue(final V value)
{
return _AbstractAttributeMap.this.put(_currentKey, value);
}
@Override
public int hashCode()
{
int result = 1;
result = 31 * result
+ ((_currentKey == null) ? 0 : _currentKey.hashCode());
return result;
}
@Override
public boolean equals(final Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final EntrySetEntry other = (EntrySetEntry) obj;
if (_currentKey == null)
{
if (other._currentKey != null)
{
return false;
}
}
else if (!_currentKey.equals(other._currentKey))
{
return false;
}
return true;
}
}
}