blob: 1ba6ec7f1e3bca428a6580c3689196a8a1d55e0b [file] [log] [blame]
package org.checkerframework.framework.util;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.lang.model.element.AnnotationMirror;
import org.checkerframework.javacutil.AnnotationUtils;
/**
* The Map interface defines some of its methods with respect to the equals method. This
* implementation of Map violates those specifications, but fulfills the same property using {@link
* AnnotationUtils#areSame}.
*
* <p>For example, the specification for the containsKey(Object key) method says: "returns true if
* and only if this map contains a mapping for a key k such that (key == null ? k == null :
* key.equals(k))." The specification for {@link AnnotationMirrorMap#containsKey} is "returns true
* if and only if this map contains a mapping for a key k such that (key == null ? k == null :
* AnnotationUtils.areSame(key, k))."
*
* <p>AnnotationMirror is an interface and not all implementing classes provide a correct equals
* method; therefore, existing implementations of Map cannot be used.
*/
public class AnnotationMirrorMap<V> implements Map<AnnotationMirror, V> {
/** The actual map to which all work is delegated. */
private final Map<AnnotationMirror, V> shadowMap;
/** Default constructor. */
public AnnotationMirrorMap() {
this.shadowMap = new TreeMap<>(AnnotationUtils::compareAnnotationMirrors);
}
/**
* Creates an annotation mirror map and adds all the mappings in {@code copy}.
*
* @param copy a map whose contents should be copied to the newly created map
*/
public AnnotationMirrorMap(Map<AnnotationMirror, ? extends V> copy) {
this();
this.putAll(copy);
}
@Override
public int size() {
return shadowMap.size();
}
@Override
public boolean isEmpty() {
return shadowMap.isEmpty();
}
@Override
public boolean containsKey(Object key) {
if (key instanceof AnnotationMirror) {
return AnnotationUtils.containsSame(shadowMap.keySet(), (AnnotationMirror) key);
} else {
return false;
}
}
@Override
public boolean containsValue(Object value) {
return shadowMap.containsValue(value);
}
@Override
public V get(Object key) {
if (key instanceof AnnotationMirror) {
AnnotationMirror keyAnno =
AnnotationUtils.getSame(shadowMap.keySet(), (AnnotationMirror) key);
if (keyAnno != null) {
return shadowMap.get(keyAnno);
}
}
return null;
}
@Override
public V put(AnnotationMirror key, V value) {
V pre = get(key);
remove(key);
shadowMap.put(key, value);
return pre;
}
@Override
public V remove(Object key) {
if (key instanceof AnnotationMirror) {
AnnotationMirror keyAnno =
AnnotationUtils.getSame(shadowMap.keySet(), (AnnotationMirror) key);
if (keyAnno != null) {
return shadowMap.remove(keyAnno);
}
}
return null;
}
@Override
public void putAll(Map<? extends AnnotationMirror, ? extends V> m) {
for (Map.Entry<? extends AnnotationMirror, ? extends V> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public void clear() {
shadowMap.clear();
}
@Override
public Set<AnnotationMirror> keySet() {
return new AnnotationMirrorSet(shadowMap.keySet());
}
@Override
public Collection<V> values() {
return shadowMap.values();
}
@Override
public Set<Map.Entry<AnnotationMirror, V>> entrySet() {
return shadowMap.entrySet();
}
@Override
public String toString() {
return shadowMap.toString();
}
}