Modified: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.java URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.java?rev=738956&r1=738955&r2=738956&view=diff ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.java (original) +++ commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.java Thu Jan 29 18:48:37 2009 @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -48,97 +48,110 @@ * <p> * NOTE: From Commons Collections 3.1, all subclasses will use <code>TreeMap</code> * and the flawed <code>createMap</code> method is ignored. - * + * * @since Commons Collections 3.0 * @version $Id$ - * + * * @author Matthew Hawthorne * @author Stephen Colebourne */ -public class DualTreeBidiMap - extends AbstractDualBidiMap implements SortedBidiMap, Serializable { +public class DualTreeBidiMap<K, V> extends AbstractDualBidiMap<K, V> implements + SortedBidiMap<K, V>, Serializable { /** Ensure serialization compatibility */ private static final long serialVersionUID = 721969328361809L; - /** The comparator to use */ - protected final Comparator comparator; + + /** The key comparator to use */ + protected final Comparator<? super K> comparator; + + /** The value comparator to use */ + protected final Comparator<? super V> valueComparator; /** * Creates an empty <code>DualTreeBidiMap</code> */ public DualTreeBidiMap() { - super(new TreeMap(), new TreeMap()); + super(new TreeMap<K, V>(), new TreeMap<V, K>()); this.comparator = null; + this.valueComparator = null; } - /** + /** * Constructs a <code>DualTreeBidiMap</code> and copies the mappings from - * specified <code>Map</code>. + * specified <code>Map</code>. * * @param map the map whose mappings are to be placed in this map */ - public DualTreeBidiMap(Map map) { - super(new TreeMap(), new TreeMap()); + public DualTreeBidiMap(Map<K, V> map) { + super(new TreeMap<K, V>(), new TreeMap<V, K>()); putAll(map); this.comparator = null; + this.valueComparator = null; } - /** + /** * Constructs a <code>DualTreeBidiMap</code> using the specified Comparator. * - * @param comparator the Comparator + * @param keyComparator the Comparator */ - public DualTreeBidiMap(Comparator comparator) { - super(new TreeMap(comparator), new TreeMap(comparator)); - this.comparator = comparator; + public DualTreeBidiMap(Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) { + super(new TreeMap<K, V>(keyComparator), new TreeMap<V, K>(valueComparator)); + this.comparator = keyComparator; + this.valueComparator = valueComparator; } - /** + /** * Constructs a <code>DualTreeBidiMap</code> that decorates the specified maps. * * @param normalMap the normal direction map * @param reverseMap the reverse direction map * @param inverseBidiMap the inverse BidiMap */ - protected DualTreeBidiMap(Map normalMap, Map reverseMap, BidiMap inverseBidiMap) { + protected DualTreeBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) { super(normalMap, reverseMap, inverseBidiMap); - this.comparator = ((SortedMap) normalMap).comparator(); + this.comparator = ((SortedMap<K, V>) normalMap).comparator(); + this.valueComparator = ((SortedMap<V, K>) reverseMap).comparator(); } /** * Creates a new instance of this object. - * + * * @param normalMap the normal direction map * @param reverseMap the reverse direction map * @param inverseMap the inverse BidiMap * @return new bidi map */ - protected BidiMap createBidiMap(Map normalMap, Map reverseMap, BidiMap inverseMap) { - return new DualTreeBidiMap(normalMap, reverseMap, inverseMap); + protected DualTreeBidiMap<V, K> createBidiMap(Map<V, K> normalMap, Map<K, V> reverseMap, BidiMap<K, V> inverseMap) { + return new DualTreeBidiMap<V, K>(normalMap, reverseMap, inverseMap); } //----------------------------------------------------------------------- - public Comparator comparator() { - return ((SortedMap) maps[0]).comparator(); + public Comparator<? super K> comparator() { + return ((SortedMap<K, V>) normalMap).comparator(); } - public Object firstKey() { - return ((SortedMap) maps[0]).firstKey(); + public Comparator<? super V> valueComparator() { + return ((SortedMap<V, K>) reverseMap).comparator(); + } - public Object lastKey() { - return ((SortedMap) maps[0]).lastKey(); + public K firstKey() { + return ((SortedMap<K, V>) normalMap).firstKey(); } - public Object nextKey(Object key) { + public K lastKey() { + return ((SortedMap<K, V>) normalMap).lastKey(); + } + + public K nextKey(K key) { if (isEmpty()) { return null; } - if (maps[0] instanceof OrderedMap) { - return ((OrderedMap) maps[0]).nextKey(key); + if (normalMap instanceof OrderedMap) { + return ((OrderedMap<K, ?>) normalMap).nextKey(key); } - SortedMap sm = (SortedMap) maps[0]; - Iterator it = sm.tailMap(key).keySet().iterator(); + SortedMap<K, V> sm = (SortedMap<K, V>) normalMap; + Iterator<K> it = sm.tailMap(key).keySet().iterator(); it.next(); if (it.hasNext()) { return it.next(); @@ -146,15 +159,15 @@ return null; } - public Object previousKey(Object key) { + public K previousKey(K key) { if (isEmpty()) { return null; } - if (maps[0] instanceof OrderedMap) { - return ((OrderedMap) maps[0]).previousKey(key); + if (normalMap instanceof OrderedMap) { + return ((OrderedMap<K, V>) normalMap).previousKey(key); } - SortedMap sm = (SortedMap) maps[0]; - SortedMap hm = sm.headMap(key); + SortedMap<K, V> sm = (SortedMap<K, V>) normalMap; + SortedMap<K, V> hm = sm.headMap(key); if (hm.isEmpty()) { return null; } @@ -167,81 +180,94 @@ * <p> * This implementation copies the elements to an ArrayList in order to * provide the forward/backward behaviour. - * + * * @return a new ordered map iterator */ - public OrderedMapIterator orderedMapIterator() { - return new BidiOrderedMapIterator(this); + public OrderedMapIterator<K, V> mapIterator() { + return new BidiOrderedMapIterator<K, V>(this); } - public SortedBidiMap inverseSortedBidiMap() { - return (SortedBidiMap) inverseBidiMap(); + public SortedBidiMap<V, K> inverseSortedBidiMap() { + return (SortedBidiMap<V, K>) inverseBidiMap(); } - public OrderedBidiMap inverseOrderedBidiMap() { - return (OrderedBidiMap) inverseBidiMap(); + public OrderedBidiMap<V, K> inverseOrderedBidiMap() { + return (OrderedBidiMap<V, K>) inverseBidiMap(); } //----------------------------------------------------------------------- - public SortedMap headMap(Object toKey) { - SortedMap sub = ((SortedMap) maps[0]).headMap(toKey); - return new ViewMap(this, sub); + public SortedMap<K, V> headMap(K toKey) { + SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).headMap(toKey); + return new ViewMap<K, V>(this, sub); } - public SortedMap tailMap(Object fromKey) { - SortedMap sub = ((SortedMap) maps[0]).tailMap(fromKey); - return new ViewMap(this, sub); + public SortedMap<K, V> tailMap(K fromKey) { + SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).tailMap(fromKey); + return new ViewMap<K, V>(this, sub); } - public SortedMap subMap(Object fromKey, Object toKey) { - SortedMap sub = ((SortedMap) maps[0]).subMap(fromKey, toKey); - return new ViewMap(this, sub); + public SortedMap<K, V> subMap(K fromKey, K toKey) { + SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).subMap(fromKey, toKey); + return new ViewMap<K, V>(this, sub); } - + + /** + * {...@inheritdoc} + */ + @Override + public SortedBidiMap<V, K> inverseBidiMap() { + return (SortedBidiMap<V, K>) super.inverseBidiMap(); + } + //----------------------------------------------------------------------- /** * Internal sorted map view. */ - protected static class ViewMap extends AbstractSortedMapDecorator { + protected static class ViewMap<K, V> extends AbstractSortedMapDecorator<K, V> { /** The parent bidi map. */ - final DualTreeBidiMap bidi; - + final DualTreeBidiMap<K, V> bidi; + /** * Constructor. * @param bidi the parent bidi map * @param sm the subMap sorted map */ - protected ViewMap(DualTreeBidiMap bidi, SortedMap sm) { + protected ViewMap(DualTreeBidiMap<K, V> bidi, SortedMap<K, V> sm) { // the implementation is not great here... - // use the maps[0] as the filtered map, but maps[1] as the full map + // use the normalMap as the filtered map, but reverseMap as the full map // this forces containsValue and clear to be overridden - super((SortedMap) bidi.createBidiMap(sm, bidi.maps[1], bidi.inverseBidiMap)); - this.bidi = (DualTreeBidiMap) map; + super(new DualTreeBidiMap<K, V>(sm, bidi.reverseMap, bidi.inverseBidiMap)); + this.bidi = (DualTreeBidiMap<K, V>) decorated(); } - + public boolean containsValue(Object value) { - // override as default implementation jumps to [1] - return bidi.maps[0].containsValue(value); + // override as default implementation uses reverseMap + return decorated().normalMap.containsValue(value); } - + public void clear() { - // override as default implementation jumps to [1] - for (Iterator it = keySet().iterator(); it.hasNext();) { + // override as default implementation uses reverseMap + for (Iterator<K> it = keySet().iterator(); it.hasNext();) { it.next(); it.remove(); } } - - public SortedMap headMap(Object toKey) { - return new ViewMap(bidi, super.headMap(toKey)); + + public SortedMap<K, V> headMap(K toKey) { + return new ViewMap<K, V>(decorated(), super.headMap(toKey)); + } + + public SortedMap<K, V> tailMap(K fromKey) { + return new ViewMap<K, V>(decorated(), super.tailMap(fromKey)); } - public SortedMap tailMap(Object fromKey) { - return new ViewMap(bidi, super.tailMap(fromKey)); + public SortedMap<K, V> subMap(K fromKey, K toKey) { + return new ViewMap<K, V>(decorated(), super.subMap(fromKey, toKey)); } - public SortedMap subMap(Object fromKey, Object toKey) { - return new ViewMap(bidi, super.subMap(fromKey, toKey)); + @Override + protected DualTreeBidiMap<K, V> decorated() { + return (DualTreeBidiMap<K, V>) super.decorated(); } } @@ -249,99 +275,101 @@ /** * Inner class MapIterator. */ - protected static class BidiOrderedMapIterator implements OrderedMapIterator, ResettableIterator { - + protected static class BidiOrderedMapIterator<K, V> implements OrderedMapIterator<K, V>, ResettableIterator<K> { + /** The parent map */ - protected final AbstractDualBidiMap parent; + protected final AbstractDualBidiMap<K, V> parent; + /** The iterator being decorated */ - protected ListIterator iterator; + protected ListIterator<Map.Entry<K, V>> iterator; + /** The last returned entry */ - private Map.Entry last = null; - + private Map.Entry<K, V> last = null; + /** * Constructor. * @param parent the parent map */ - protected BidiOrderedMapIterator(AbstractDualBidiMap parent) { + protected BidiOrderedMapIterator(AbstractDualBidiMap<K, V> parent) { super(); this.parent = parent; - iterator = new ArrayList(parent.entrySet()).listIterator(); + iterator = new ArrayList<Map.Entry<K, V>>(parent.entrySet()).listIterator(); } - + public boolean hasNext() { return iterator.hasNext(); } - - public Object next() { - last = (Map.Entry) iterator.next(); + + public K next() { + last = iterator.next(); return last.getKey(); } - + public boolean hasPrevious() { return iterator.hasPrevious(); } - - public Object previous() { - last = (Map.Entry) iterator.previous(); + + public K previous() { + last = iterator.previous(); return last.getKey(); } - + public void remove() { iterator.remove(); parent.remove(last.getKey()); last = null; } - - public Object getKey() { + + public K getKey() { if (last == null) { throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()"); } return last.getKey(); } - public Object getValue() { + public V getValue() { if (last == null) { throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()"); } return last.getValue(); } - - public Object setValue(Object value) { + + public V setValue(V value) { if (last == null) { throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()"); } - if (parent.maps[1].containsKey(value) && - parent.maps[1].get(value) != last.getKey()) { + if (parent.reverseMap.containsKey(value) && + parent.reverseMap.get(value) != last.getKey()) { throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map"); } return parent.put(last.getKey(), value); } - + public void reset() { - iterator = new ArrayList(parent.entrySet()).listIterator(); + iterator = new ArrayList<Map.Entry<K, V>>(parent.entrySet()).listIterator(); last = null; } - + public String toString() { if (last != null) { return "MapIterator[" + getKey() + "=" + getValue() + "]"; - } else { - return "MapIterator[]"; } + return "MapIterator[]"; } } - + // Serialization //----------------------------------------------------------------------- private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); - out.writeObject(maps[0]); + out.writeObject(normalMap); } + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - maps[0] = new TreeMap(comparator); - maps[1] = new TreeMap(comparator); + normalMap = new TreeMap(comparator); + reverseMap = new TreeMap(comparator); Map map = (Map) in.readObject(); putAll(map); }