110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipackage annotations.util.coll;
210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
3a74f2668d253bb9375805db0f23a01e30ddfba8fwdietlimport java.util.*;
4a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl
5a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl/*>>>
643367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport org.checkerframework.checker.nullness.qual.*;
7a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl*/
810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali/**
1010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * A simple implementation of {@link KeyedSet} backed by an insertion-order
1110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link java.util.LinkedHashMap} and its
1210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link java.util.LinkedHashMap#values() value collection}.
1310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */
1410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipublic class LinkedHashKeyedSet<K, V> extends AbstractSet<V> implements KeyedSet<K, V> {
1510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    private final Keyer<? extends K, ? super V> keyer;
1610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
1710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    private final Map<K, V> theMap = new LinkedHashMap<K, V>();
1810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
1910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    final Collection<V> theValues = theMap.values();
2010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
2110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
2210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * Constructs a {@link LinkedHashKeyedSet} that uses the given
2310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@link Keyer} to obtain keys for elements.
2410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
2510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    public LinkedHashKeyedSet(Keyer<? extends K, ? super V> keyer) {
2610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        this.keyer = keyer;
2710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
2810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
2910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
3010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
3110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
3210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
3310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    public int size() {
3410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return theValues.size();
3510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
3610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
3710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
3810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
3910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
4010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
413aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst    public boolean contains(Object o) {
4210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return theValues.contains(o);
4310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
4410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
4510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    private class KeyedSetIterator implements Iterator<V> {
46a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl        private final Iterator<V> itr = theValues.iterator();
4710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
48a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl        @Override
493aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst        public boolean hasNext() {
5010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            return itr.hasNext();
5110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        }
5210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
53a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl        @Override
543aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst        public V next() {
5510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            return itr.next();
5610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        }
5710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
58a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl        @Override
5910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        public void remove() {
6010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            itr.remove();
6110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        }
6210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
6310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        KeyedSetIterator() {
6410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        }
6510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
6610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
6710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
6810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
6910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
7010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
713aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst    public Iterator<V> iterator() {
7210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return new KeyedSetIterator();
7310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
7410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
7510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
7610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
7710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
7810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
793aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst    public Object[] toArray() {
8010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return theValues.toArray();
8110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
8210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
8310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
8410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
8510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
8610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
873aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst    public <T> T[] toArray(T[] a) {
8810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return theValues.toArray(a);
8910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
9010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
9110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    private boolean checkAdd(int behavior, V old) {
9210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        switch (behavior) {
9310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        case REPLACE:
9410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            remove(old);
9510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            return true;
9610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        case IGNORE:
9710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            return false;
9810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        case THROW_EXCEPTION:
9910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            throw new IllegalStateException();
10010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        default:
10110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            throw new IllegalArgumentException();
10210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        }
10310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
10410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
1053aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst    private static boolean eq(Object x, Object y) {
10610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return x == y || (x != null && x.equals(y));
10710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
10810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
10910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
11010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
11110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
112a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl    @Override
11310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    public V add(V o, int conflictBehavior, int equalBehavior) {
11410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        K key = keyer.getKeyFor(o);
11510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        V old = theMap.get(key);
11610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        if (old == null
11710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali                || (eq(o, old) ? checkAdd(equalBehavior, old) : checkAdd(
11810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali                        conflictBehavior, old)))
11910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            theMap.put(key, o);
12010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return old;
12110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
12210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
12310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
12410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
12510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
12610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
12710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    public boolean add(V o) {
12810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return add(o, THROW_EXCEPTION, IGNORE) == null;
12910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
13010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
13110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
13210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
13310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
13410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
1353aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst    public boolean remove(Object o) {
13610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return theValues.remove(o);
13710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
13810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
13910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
14010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
14110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
14210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
14310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    public boolean addAll(Collection<? extends V> c) {
14410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        boolean changed = false;
145f363307b8c8b78b369f6770b2d0b95eccf6754c9Michael Ernst        for (V o : c) {
14610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali            changed |= add(o);
147f363307b8c8b78b369f6770b2d0b95eccf6754c9Michael Ernst        }
14810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return changed;
14910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
15010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
15110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
15210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
15310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
15410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    @Override
15510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    public void clear() {
15610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        theValues.clear();
15710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
15810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
15910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
16010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
16110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
162a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl    @Override
1633aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst    public Keyer<? extends K, ? super V> getKeyer() {
16410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return keyer;
16510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
16610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
16710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
16810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
16910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
170a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl    @Override
17110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    public V replace(V v) {
17210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return theMap.put(keyer.getKeyFor(v), v);
17310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
17410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
17510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    /**
17610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     * {@inheritDoc}
17710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali     */
178a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl    @Override
17910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    public V lookup(K k) {
18010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali        return theMap.get(k);
18110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    }
18210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali
18310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    // Use inherited equals and hashCode algorithms because
18410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali    // those of HashMap.Values are broken!
18510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali}
186