/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2012 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util;
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Map to wrap another map that does not allow null key or value.
*
* @author rgansevles
*
*/
public class AllowNullMap<K, V> extends AbstractMap<K, V> implements Serializable
{
private static final Object NULL = new Object()
{
@Override
public String toString()
{
return "<NULL>"; //$NON-NLS-1$
}
};
private final Map<K, V> map;
public AllowNullMap(Map<K, V> map)
{
this.map = map;
}
@SuppressWarnings("unchecked")
@Override
public V put(K key, V value)
{
Object oldValue = map.put((K)(key == null ? NULL : key), (V)(value == null ? NULL : value));
return (V)(oldValue == NULL ? null : oldValue);
}
@SuppressWarnings("unchecked")
@Override
public V get(Object key)
{
Object get = map.get(key == null ? NULL : key);
return (V)(get == NULL ? null : get);
}
@Override
public V remove(Object key)
{
return map.remove(key == null ? NULL : key);
}
@Override
public boolean containsKey(Object key)
{
return map.containsKey(key == null ? NULL : key);
}
@Override
public Set<Entry<K, V>> entrySet()
{
return new NullkeyEntrySet<K, V>(map.entrySet());
}
private static class NullkeyEntrySet<K, V> extends AbstractSet<Entry<K, V>>
{
private final Set<Entry<K, V>> set;
public NullkeyEntrySet(Set<Entry<K, V>> set)
{
this.set = set;
}
@Override
public int size()
{
return set.size();
}
@Override
public Iterator<Entry<K, V>> iterator()
{
final Iterator<Entry<K, V>> iterator = set.iterator();
return new Iterator<Map.Entry<K, V>>()
{
public boolean hasNext()
{
return iterator.hasNext();
}
public Entry<K, V> next()
{
final Entry<K, V> next = iterator.next();
return new Entry<K, V>()
{
@SuppressWarnings("unchecked")
public K getKey()
{
Object key = next.getKey();
return (K)(key == NULL ? null : key);
}
@SuppressWarnings("unchecked")
public V getValue()
{
Object value = next.getValue();
return (V)(value == NULL ? null : value);
}
@SuppressWarnings("unchecked")
public V setValue(V value)
{
Object oldval = next.setValue((V)(value == null ? NULL : value));
return (V)(oldval == NULL ? null : oldval);
}
};
}
public void remove()
{
iterator.remove();
}
};
}
}
}