001package components.map;
002
003import java.util.HashMap;
004import java.util.Iterator;
005import java.util.NoSuchElementException;
006import java.util.Set;
007
008/**
009 * {@code Map} represented as a {@link java.util.Map java.util.Map} with
010 * implementations of primary methods.
011 *
012 * @param <K>
013 *            type of {@code Map} domain (key) entries
014 * @param <V>
015 *            type of {@code Map} range (associated value) entries
016 * @correspondence this = [value of $this]
017 */
018public class Map1L<K, V> extends MapSecondary<K, V> {
019
020    /*
021     * Private members --------------------------------------------------------
022     */
023
024    /**
025     * Representation of {@code this}.
026     */
027    private java.util.Map<K, V> rep;
028
029    /**
030     * Creator of initial representation.
031     */
032    private void createNewRep() {
033        this.rep = new HashMap<K, V>();
034    }
035
036    /*
037     * Constructors -----------------------------------------------------------
038     */
039
040    /**
041     * No-argument constructor.
042     */
043    public Map1L() {
044        this.createNewRep();
045    }
046
047    /*
048     * Standard methods -------------------------------------------------------
049     */
050
051    @SuppressWarnings("unchecked")
052    @Override
053    public final Map<K, V> newInstance() {
054        try {
055            return this.getClass().getConstructor().newInstance();
056        } catch (ReflectiveOperationException e) {
057            throw new AssertionError(
058                    "Cannot construct object of type " + this.getClass());
059        }
060    }
061
062    @Override
063    public final void clear() {
064        this.createNewRep();
065    }
066
067    @Override
068    public final void transferFrom(Map<K, V> source) {
069        assert source != null : "Violation of: source is not null";
070        assert source != this : "Violation of: source is not this";
071        assert source instanceof Map1L<?, ?>
072                : "Violation of: source is of dynamic type Map1L<?,?>";
073        /*
074         * This cast cannot fail since the assert above would have stopped
075         * execution in that case: source must be of dynamic type Map2<?,?>, and
076         * the ?,? must be K,V or the call would not have compiled.
077         */
078        Map1L<K, V> localSource = (Map1L<K, V>) source;
079        this.rep = localSource.rep;
080        localSource.createNewRep();
081    }
082
083    /*
084     * Kernel methods ---------------------------------------------------------
085     */
086
087    @Override
088    public final void add(K key, V value) {
089        assert key != null : "Violation of: key is not null";
090        assert value != null : "Violation of: value is not null";
091        assert !this.hasKey(key) : "Violation of: key is not in DOMAIN(this)";
092        this.rep.put(key, value);
093    }
094
095    @Override
096    public final Map.Pair<K, V> remove(K key) {
097        assert key != null : "Violation of: key is not null";
098        assert this.hasKey(key) : "Violation of: key is in DOMAIN(this)";
099        /*
100         * The following "obvious" code is incorrect because it creates an alias
101         * where one is not specified in the contract (because no alias is
102         * needed). This is a design flaw in java.util.Map that means Map1L is
103         * not a competitive implementation of MapKernel when assertion-checking
104         * is disabled.
105         */
106        // return new SimplePair<K, V>(key, this.rep.remove(key));
107        /*
108         * Note: null will never be returned, but we still need to initialize.
109         */
110        K keyRemoved = null;
111        Set<K> keys = this.rep.keySet();
112        for (K x : keys) {
113            if (x.equals(key)) {
114                keyRemoved = x;
115                break;
116            }
117        }
118        V valueRemoved = this.rep.remove(keyRemoved);
119        return new SimplePair<K, V>(keyRemoved, valueRemoved);
120    }
121
122    @Override
123    public final Pair<K, V> removeAny() {
124        assert this.size() > 0 : "Violation of: this /= empty_set";
125        Iterator<java.util.Map.Entry<K, V>> it = this.rep.entrySet().iterator();
126        java.util.Map.Entry<K, V> entry = it.next();
127        it.remove();
128        return new SimplePair<K, V>(entry.getKey(), entry.getValue());
129    }
130
131    @Override
132    public final V value(K key) {
133        assert key != null : "Violation of: key is not null";
134        assert this.hasKey(key) : "Violation of: key is in DOMAIN(this)";
135        return this.rep.get(key);
136    }
137
138    @Override
139    public final boolean hasKey(K key) {
140        assert key != null : "Violation of: key is not null";
141        return this.rep.containsKey(key);
142    }
143
144    @Override
145    public final int size() {
146        return this.rep.size();
147    }
148
149    @Override
150    public final Iterator<Pair<K, V>> iterator() {
151        return new Map1LIterator();
152    }
153
154    /**
155     * Implementation of {@code Iterator} interface for {@code Map1L}.
156     */
157    private final class Map1LIterator implements Iterator<Pair<K, V>> {
158
159        /**
160         * Representation iterator.
161         */
162        private final Iterator<java.util.Map.Entry<K, V>> iterator;
163
164        /**
165         * No-argument constructor.
166         */
167        private Map1LIterator() {
168            this.iterator = Map1L.this.rep.entrySet().iterator();
169        }
170
171        @Override
172        public boolean hasNext() {
173            return this.iterator.hasNext();
174        }
175
176        @Override
177        public Pair<K, V> next() {
178            assert this.hasNext() : "Violation of: ~this.unseen /= <>";
179            if (!this.hasNext()) {
180                /*
181                 * Exception is supposed to be thrown in this case, but with
182                 * assertion-checking enabled it cannot happen because of assert
183                 * above.
184                 */
185                throw new NoSuchElementException();
186            }
187            java.util.Map.Entry<K, V> entry = this.iterator.next();
188            return new SimplePair<K, V>(entry.getKey(), entry.getValue());
189        }
190
191        @Override
192        public void remove() {
193            throw new UnsupportedOperationException("remove operation not supported");
194        }
195
196    }
197
198    /*
199     * Other methods (overridden for performance reasons) ---------------------
200     */
201
202    @Override
203    public final V replaceValue(K key, V value) {
204        assert key != null : "Violation of: key is not null";
205        assert value != null : "Violation of: value is not null";
206        assert this.hasKey(key) : "Violation of: key is in DOMAIN(this)";
207        return this.rep.put(key, value);
208    }
209
210}