package org.jboss.resteasy.util;
import org.jboss.resteasy.specimpl.MultivaluedTreeMap;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
Author: Bill Burke Version: $Revision: 1 $
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@SuppressWarnings("unchecked")
//public class CaseInsensitiveMap<V> implements MultivaluedMap<String, V>, Serializable
public class CaseInsensitiveMap<V> extends MultivaluedTreeMap<String, V>
{
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
private static class CaseInsensitiveComparator
implements Comparator<String>, java.io.Serializable {
public int compare(String s1, String s2) {
if (s1 == s2) return 0;
int n1 = 0;
// null check is different than JDK version of this method
if (s1 != null) n1 = s1.length();
int n2 = 0;
if (s2 != null) n2 = s2.length();
int min = Math.min(n1, n2);
for (int i = 0; i < min; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
// No overflow because of numeric promotion
return c1 - c2;
}
}
}
return n1 - n2;
}
}
public CaseInsensitiveMap()
{
super(CASE_INSENSITIVE_ORDER);
}
/*
private static class KeySetWrapper implements Set<String>
{
private Set<CaseInsensitiveKey> keys;
public KeySetWrapper(Set<CaseInsensitiveKey> keys)
{
this.keys = keys;
}
public int size()
{
return keys.size();
}
public boolean isEmpty()
{
return keys.isEmpty();
}
public boolean contains(Object o)
{
return keys.contains(new CaseInsensitiveKey((String) o));
}
public Iterator<String> iterator()
{
return new Iterator<String>()
{
private Iterator<CaseInsensitiveKey> it = keys.iterator();
public boolean hasNext()
{
return it.hasNext();
}
public String next()
{
return it.next().key;
}
public void remove()
{
it.remove();
}
};
}
public Object[] toArray()
{
return toArray(new String[keys.size()]);
}
public <T> T[] toArray(T[] ks)
{
int i = 0;
for (CaseInsensitiveKey key : keys)
{
ks[i++] = (T) key.key;
}
return ks;
}
public boolean add(String key)
{
return keys.add(new CaseInsensitiveKey(key));
}
public boolean remove(Object o)
{
return keys.remove(new CaseInsensitiveKey(o.toString()));
}
public boolean containsAll(Collection<?> objects)
{
HashSet<CaseInsensitiveKey> objs = new HashSet<CaseInsensitiveKey>();
for (Object o : objects)
{
objs.add(new CaseInsensitiveKey(o.toString()));
}
return keys.containsAll(objs);
}
public boolean addAll(Collection<? extends String> objects)
{
HashSet<CaseInsensitiveKey> objs = new HashSet<CaseInsensitiveKey>();
for (Object o : objects)
{
objs.add(new CaseInsensitiveKey(o.toString()));
}
return keys.addAll(objs);
}
public boolean retainAll(Collection<?> objects)
{
HashSet<CaseInsensitiveKey> objs = new HashSet<CaseInsensitiveKey>();
for (Object o : objects)
{
objs.add(new CaseInsensitiveKey(o.toString()));
}
return keys.retainAll(objects);
}
public boolean removeAll(Collection<?> objects)
{
HashSet<CaseInsensitiveKey> objs = new HashSet<CaseInsensitiveKey>();
for (Object o : objects)
{
objs.add(new CaseInsensitiveKey(o.toString()));
}
return keys.removeAll(objects);
}
public void clear()
{
keys.clear();
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || !(o instanceof Set)) return false;
Set<String> strings = (Set<String>) o;
if (size() != strings.size()) return false;
for (String string : strings)
{
if (!contains(string)) return false;
}
return true;
}
@Override
public int hashCode()
{
return keys.hashCode();
}
}
private static class EntrySetWrapper<V> implements Set<Entry<String, V>>
{
private Set<Entry<CaseInsensitiveKey, V>> entrySet;
private EntrySetWrapper(Set<Entry<CaseInsensitiveKey, V>> entrySet)
{
this.entrySet = entrySet;
}
public int size()
{
return entrySet.size();
}
public boolean isEmpty()
{
return entrySet.isEmpty();
}
public boolean contains(Object o)
{
if (!(o instanceof Entry)) return false;
return entrySet.contains(new EntryWrapper<V>((Entry<String, V>) o));
}
public Iterator<Entry<String, V>> iterator()
{
return new Iterator<Entry<String, V>>()
{
Iterator<Entry<CaseInsensitiveKey, V>> it = entrySet.iterator();
public boolean hasNext()
{
return it.hasNext();
}
public Entry<String, V> next()
{
return new EntryDelegate<V>(it.next());
}
public void remove()
{
it.remove();
}
};
}
public Object[] toArray()
{
Entry<String, V>[] array = new Entry[entrySet.size()];
return toArray(array);
}
public <T> T[] toArray(T[] ts)
{
Entry<String, V>[] array = (Entry<String, V>[]) ts;
int i = 0;
for (Entry<CaseInsensitiveKey, V> entry : entrySet)
{
array[i++] = new EntryDelegate(entry);
}
return (T[]) array;
}
public boolean add(Entry<String, V> stringVEntry)
{
entrySet.add(new EntryWrapper<V>(stringVEntry));
return false;
}
public boolean remove(Object o)
{
return entrySet.remove(new EntryWrapper<V>((Entry<String, V>) o));
}
public boolean containsAll(Collection<?> objects)
{
Collection<Entry<String, V>> list = (Collection<Entry<String, V>>) objects;
HashSet<Entry<CaseInsensitiveKey, V>> set = new HashSet<Entry<CaseInsensitiveKey, V>>();
for (Entry<String, V> entry : list)
{
set.add(new EntryWrapper<V>(entry));
}
return entrySet.containsAll(set);
}
public boolean addAll(Collection<? extends Entry<String, V>> entries)
{
HashSet<Entry<CaseInsensitiveKey, V>> set = new HashSet<Entry<CaseInsensitiveKey, V>>();
for (Entry<String, V> entry : entries)
{
set.add(new EntryWrapper<V>(entry));
}
return entrySet.addAll(set);
}
public boolean retainAll(Collection<?> objects)
{
Collection<Entry<String, V>> list = (Collection<Entry<String, V>>) objects;
HashSet<Entry<CaseInsensitiveKey, V>> set = new HashSet<Entry<CaseInsensitiveKey, V>>();
for (Entry<String, V> entry : list)
{
set.add(new EntryWrapper<V>(entry));
}
return entrySet.retainAll(set);
}
public boolean removeAll(Collection<?> objects)
{
Collection<Entry<String, V>> list = (Collection<Entry<String, V>>) objects;
HashSet<Entry<CaseInsensitiveKey, V>> set = new HashSet<Entry<CaseInsensitiveKey, V>>();
for (Entry<String, V> entry : list)
{
set.add(new EntryWrapper<V>(entry));
}
return entrySet.removeAll(set);
}
public void clear()
{
entrySet.clear();
}
private class EntryWrapper<T> implements Entry<CaseInsensitiveKey, T>
{
private CaseInsensitiveKey key;
private T value;
public EntryWrapper(Entry<String, T> entry)
{
key = new CaseInsensitiveKey(entry.getKey());
value = entry.getValue();
}
public CaseInsensitiveKey getKey()
{
return key;
}
public T getValue()
{
return value;
}
public T setValue(T v)
{
T tmp = value;
value = v;
return tmp;
}
}
private class EntryDelegate<T> implements Entry<String, T>
{
private Entry<CaseInsensitiveKey, T> entry;
private EntryDelegate(Entry<CaseInsensitiveKey, T> entry)
{
this.entry = entry;
}
public final String getKey()
{
return entry.getKey().key;
}
public final T getValue()
{
return entry.getValue();
}
public final T setValue(T v)
{
return entry.setValue(v);
}
}
}
private static class CaseInsensitiveKey implements Serializable
{
private static final long serialVersionUID = 6249456709345532524L;
private String key;
private int hashCode = 0;
private String tlc;
private CaseInsensitiveKey(String key)
{
this.key = key;
if (key != null)
{
tlc = key.toLowerCase();
hashCode = tlc.hashCode();
}
}
public final boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CaseInsensitiveKey that = (CaseInsensitiveKey) o;
if (tlc == that.tlc) return true;
if (tlc == null || that.tlc == null) return false;
return tlc.equals(that.tlc);
}
public final int hashCode()
{
return hashCode;
}
public final String toString()
{
return key;
}
}
private MultivaluedMap<CaseInsensitiveKey, V> map = new MultivaluedHashMap<CaseInsensitiveKey, V>();
public void putSingle(String key, V value)
{
map.putSingle(new CaseInsensitiveKey(key), value);
}
public void add(String key, V value)
{
map.add(new CaseInsensitiveKey(key), value);
}
public V getFirst(String key)
{
return map.getFirst(new CaseInsensitiveKey(key));
}
public final int size()
{
return map.size();
}
public boolean isEmpty()
{
return map.isEmpty();
}
public boolean containsKey(Object o)
{
String key = o == null ? null : o.toString();
return map.containsKey(new CaseInsensitiveKey(key));
}
public boolean containsValue(Object o)
{
return map.containsValue(o);
}
public List<V> get(Object o)
{
String key = o == null ? null : o.toString();
return map.get(new CaseInsensitiveKey(key));
}
public List<V> put(String s, List<V> vs)
{
return map.put(new CaseInsensitiveKey(s), vs);
}
public List<V> remove(Object o)
{
String key = o == null ? null : o.toString();
return map.remove(new CaseInsensitiveKey(key));
}
private List<V> getMapList(CaseInsensitiveKey key)
{
List<V> list = map.get(key);
if (list == null)
map.put(key, list = new ArrayList<V>());
return list;
}
public final void putAll(Map otherMap)
{
if (otherMap instanceof CaseInsensitiveMap)
{
CaseInsensitiveMap otherCaseInsensitiveMap = ((CaseInsensitiveMap) otherMap);
Set<Map.Entry<CaseInsensitiveKey, List<V>>> es = otherCaseInsensitiveMap.map.entrySet();
for (Entry<CaseInsensitiveKey, List<V>> entry : es)
{
getMapList(entry.getKey()).addAll(entry.getValue());
}
}
else
{
for (Map.Entry<String, List<V>> entry : (Set<Entry<String, List<V>>>) otherMap.entrySet())
{
getMapList(new CaseInsensitiveKey(entry.getKey())).addAll(entry.getValue());
}
}
}
public void clear()
{
map.clear();
}
public Set<String> keySet()
{
return new KeySetWrapper(map.keySet());
}
public Collection<List<V>> values()
{
return map.values();
}
public Set<Entry<String, List<V>>> entrySet()
{
return new EntrySetWrapper<List<V>>(map.entrySet());
}
@Override
public void addAll(String key, V... newValues)
{
for (V value : newValues)
{
add(key, value);
}
}
@Override
public void addAll(String key, List<V> valueList)
{
for (V value : valueList)
{
add(key, value);
}
}
@Override
public void addFirst(String key, V value)
{
List<V> list = get(key);
if (list == null)
{
add(key, value);
return;
}
else
{
list.add(0, value);
}
}
@Override
public boolean equalsIgnoreValueOrder(MultivaluedMap<String, V> omap) {
if (this == omap) {
return true;
}
if (!keySet().equals(omap.keySet())) {
return false;
}
for (Entry<String, List<V>> e : entrySet()) {
List<V> olist = omap.get(e.getKey());
if (e.getValue().size() != olist.size()) {
return false;
}
for (V v : e.getValue()) {
if (!olist.contains(v)) {
return false;
}
}
}
return true;
}
*/
}