• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect.testing;
18 
19 import java.io.Serializable;
20 import java.util.Collection;
21 import java.util.Comparator;
22 import java.util.Map;
23 import java.util.NavigableMap;
24 import java.util.NavigableSet;
25 import java.util.Set;
26 import java.util.SortedMap;
27 import java.util.TreeMap;
28 
29 /**
30  * A wrapper around {@code TreeMap} that aggressively checks to see if keys are
31  * mutually comparable. This implementation passes the navigable map test
32  * suites.
33  *
34  * @author Louis Wasserman
35  */
36 public final class SafeTreeMap<K, V>
37     implements Serializable, NavigableMap<K, V> {
38   @SuppressWarnings("unchecked")
39   private static final Comparator NATURAL_ORDER = new Comparator<Comparable>() {
40     @Override public int compare(Comparable o1, Comparable o2) {
41       return o1.compareTo(o2);
42     }
43   };
44   private final NavigableMap<K, V> delegate;
45 
SafeTreeMap()46   public SafeTreeMap() {
47     this(new TreeMap<K, V>());
48   }
49 
SafeTreeMap(Comparator<? super K> comparator)50   public SafeTreeMap(Comparator<? super K> comparator) {
51     this(new TreeMap<K, V>(comparator));
52   }
53 
SafeTreeMap(Map<? extends K, ? extends V> map)54   public SafeTreeMap(Map<? extends K, ? extends V> map) {
55     this(new TreeMap<K, V>(map));
56   }
57 
SafeTreeMap(SortedMap<K, ? extends V> map)58   public SafeTreeMap(SortedMap<K, ? extends V> map) {
59     this(new TreeMap<K, V>(map));
60   }
61 
SafeTreeMap(NavigableMap<K, V> delegate)62   private SafeTreeMap(NavigableMap<K, V> delegate) {
63     this.delegate = delegate;
64     if (delegate == null) {
65       throw new NullPointerException();
66     }
67     for (K k : keySet()) {
68       checkValid(k);
69     }
70   }
71 
ceilingEntry(K key)72   @Override public Entry<K, V> ceilingEntry(K key) {
73     return delegate.ceilingEntry(checkValid(key));
74   }
75 
ceilingKey(K key)76   @Override public K ceilingKey(K key) {
77     return delegate.ceilingKey(checkValid(key));
78   }
79 
clear()80   @Override public void clear() {
81     delegate.clear();
82   }
83 
84   @SuppressWarnings("unchecked")
comparator()85   @Override public Comparator<? super K> comparator() {
86     Comparator<? super K> comparator = delegate.comparator();
87     if (comparator == null) {
88       comparator = NATURAL_ORDER;
89     }
90     return comparator;
91   }
92 
containsKey(Object key)93   @Override public boolean containsKey(Object key) {
94     try {
95       return delegate.containsKey(checkValid(key));
96     } catch (NullPointerException e) {
97       return false;
98     } catch (ClassCastException e) {
99       return false;
100     }
101   }
102 
containsValue(Object value)103   @Override public boolean containsValue(Object value) {
104     return delegate.containsValue(value);
105   }
106 
descendingKeySet()107   @Override public NavigableSet<K> descendingKeySet() {
108     return delegate.descendingKeySet();
109   }
110 
descendingMap()111   @Override public NavigableMap<K, V> descendingMap() {
112     return new SafeTreeMap<K, V>(delegate.descendingMap());
113   }
114 
entrySet()115   @Override public Set<Entry<K, V>> entrySet() {
116     return delegate.entrySet();
117   }
118 
firstEntry()119   @Override public Entry<K, V> firstEntry() {
120     return delegate.firstEntry();
121   }
122 
firstKey()123   @Override public K firstKey() {
124     return delegate.firstKey();
125   }
126 
floorEntry(K key)127   @Override public Entry<K, V> floorEntry(K key) {
128     return delegate.floorEntry(checkValid(key));
129   }
130 
floorKey(K key)131   @Override public K floorKey(K key) {
132     return delegate.floorKey(checkValid(key));
133   }
134 
get(Object key)135   @Override public V get(Object key) {
136     return delegate.get(checkValid(key));
137   }
138 
headMap(K toKey)139   @Override public SortedMap<K, V> headMap(K toKey) {
140     return headMap(toKey, false);
141   }
142 
headMap(K toKey, boolean inclusive)143   @Override public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
144     return new SafeTreeMap<K, V>(
145         delegate.headMap(checkValid(toKey), inclusive));
146   }
147 
higherEntry(K key)148   @Override public Entry<K, V> higherEntry(K key) {
149     return delegate.higherEntry(checkValid(key));
150   }
151 
higherKey(K key)152   @Override public K higherKey(K key) {
153     return delegate.higherKey(checkValid(key));
154   }
155 
isEmpty()156   @Override public boolean isEmpty() {
157     return delegate.isEmpty();
158   }
159 
keySet()160   @Override public NavigableSet<K> keySet() {
161     return navigableKeySet();
162   }
163 
lastEntry()164   @Override public Entry<K, V> lastEntry() {
165     return delegate.lastEntry();
166   }
167 
lastKey()168   @Override public K lastKey() {
169     return delegate.lastKey();
170   }
171 
lowerEntry(K key)172   @Override public Entry<K, V> lowerEntry(K key) {
173     return delegate.lowerEntry(checkValid(key));
174   }
175 
lowerKey(K key)176   @Override public K lowerKey(K key) {
177     return delegate.lowerKey(checkValid(key));
178   }
179 
navigableKeySet()180   @Override public NavigableSet<K> navigableKeySet() {
181     return delegate.navigableKeySet();
182   }
183 
pollFirstEntry()184   @Override public Entry<K, V> pollFirstEntry() {
185     return delegate.pollFirstEntry();
186   }
187 
pollLastEntry()188   @Override public Entry<K, V> pollLastEntry() {
189     return delegate.pollLastEntry();
190   }
191 
put(K key, V value)192   @Override public V put(K key, V value) {
193     return delegate.put(checkValid(key), value);
194   }
195 
putAll(Map<? extends K, ? extends V> map)196   @Override public void putAll(Map<? extends K, ? extends V> map) {
197     for (K key : map.keySet()) {
198       checkValid(key);
199     }
200     delegate.putAll(map);
201   }
202 
remove(Object key)203   @Override public V remove(Object key) {
204     return delegate.remove(checkValid(key));
205   }
206 
size()207   @Override public int size() {
208     return delegate.size();
209   }
210 
subMap( K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)211   @Override public NavigableMap<K, V> subMap(
212       K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
213     return new SafeTreeMap<K, V>(delegate.subMap(
214         checkValid(fromKey), fromInclusive, checkValid(toKey), toInclusive));
215   }
216 
subMap(K fromKey, K toKey)217   @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
218     return subMap(fromKey, true, toKey, false);
219   }
220 
tailMap(K fromKey)221   @Override public SortedMap<K, V> tailMap(K fromKey) {
222     return tailMap(fromKey, true);
223   }
224 
tailMap(K fromKey, boolean inclusive)225   @Override public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
226     return new SafeTreeMap<K, V>(
227         delegate.tailMap(checkValid(fromKey), inclusive));
228   }
229 
values()230   @Override public Collection<V> values() {
231     return delegate.values();
232   }
233 
checkValid(T t)234   private <T> T checkValid(T t) {
235     // a ClassCastException is what's supposed to happen!
236     @SuppressWarnings("unchecked")
237     K k = (K) t;
238     comparator().compare(k, k);
239     return t;
240   }
241 
equals(Object obj)242   @Override public boolean equals(Object obj) {
243     return delegate.equals(obj);
244   }
245 
hashCode()246   @Override public int hashCode() {
247     return delegate.hashCode();
248   }
249 
toString()250   @Override public String toString() {
251     return delegate.toString();
252   }
253 
254   private static final long serialVersionUID = 0L;
255 }
256