| 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(); |
| } |
| } |