package org.checkerframework.framework.util; import static org.checkerframework.javacutil.AnnotationUtils.annotationOrdering; 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 = new TreeMap<>(annotationOrdering()); public AnnotationMirrorMap() {} public AnnotationMirrorMap(Map<AnnotationMirror, ? extends V> primaries) { this.putAll(primaries); } @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 (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<Entry<AnnotationMirror, V>> entrySet() { return shadowMap.entrySet(); } }