• 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 com.google.common.annotations.GwtIncompatible;
20 import com.google.errorprone.annotations.CanIgnoreReturnValue;
21 import java.io.Serializable;
22 import java.util.Collection;
23 import java.util.Comparator;
24 import java.util.Iterator;
25 import java.util.NavigableSet;
26 import java.util.SortedSet;
27 import java.util.TreeSet;
28 import org.checkerframework.checker.nullness.qual.Nullable;
29 
30 /**
31  * A wrapper around {@code TreeSet} that aggressively checks to see if elements are mutually
32  * comparable. This implementation passes the navigable set test suites.
33  *
34  * @author Louis Wasserman
35  */
36 @GwtIncompatible
37 public final class SafeTreeSet<E> implements Serializable, NavigableSet<E> {
38   @SuppressWarnings("unchecked")
39   private static final Comparator<Object> NATURAL_ORDER =
40       new Comparator<Object>() {
41         @Override
42         public int compare(Object o1, Object o2) {
43           return ((Comparable<Object>) o1).compareTo(o2);
44         }
45       };
46 
47   private final NavigableSet<E> delegate;
48 
SafeTreeSet()49   public SafeTreeSet() {
50     this(new TreeSet<E>());
51   }
52 
SafeTreeSet(Collection<? extends E> collection)53   public SafeTreeSet(Collection<? extends E> collection) {
54     this(new TreeSet<E>(collection));
55   }
56 
SafeTreeSet(Comparator<? super E> comparator)57   public SafeTreeSet(Comparator<? super E> comparator) {
58     this(new TreeSet<E>(comparator));
59   }
60 
SafeTreeSet(SortedSet<E> set)61   public SafeTreeSet(SortedSet<E> set) {
62     this(new TreeSet<E>(set));
63   }
64 
SafeTreeSet(NavigableSet<E> delegate)65   private SafeTreeSet(NavigableSet<E> delegate) {
66     this.delegate = delegate;
67     for (E e : this) {
68       checkValid(e);
69     }
70   }
71 
72   @Override
add(E element)73   public boolean add(E element) {
74     return delegate.add(checkValid(element));
75   }
76 
77   @Override
addAll(Collection<? extends E> collection)78   public boolean addAll(Collection<? extends E> collection) {
79     for (E e : collection) {
80       checkValid(e);
81     }
82     return delegate.addAll(collection);
83   }
84 
85   @Override
ceiling(E e)86   public @Nullable E ceiling(E e) {
87     return delegate.ceiling(checkValid(e));
88   }
89 
90   @Override
clear()91   public void clear() {
92     delegate.clear();
93   }
94 
95   @SuppressWarnings("unchecked")
96   @Override
comparator()97   public Comparator<? super E> comparator() {
98     Comparator<? super E> comparator = delegate.comparator();
99     if (comparator == null) {
100       comparator = (Comparator<? super E>) NATURAL_ORDER;
101     }
102     return comparator;
103   }
104 
105   @Override
contains(Object object)106   public boolean contains(Object object) {
107     return delegate.contains(checkValid(object));
108   }
109 
110   @Override
containsAll(Collection<?> c)111   public boolean containsAll(Collection<?> c) {
112     return delegate.containsAll(c);
113   }
114 
115   @Override
descendingIterator()116   public Iterator<E> descendingIterator() {
117     return delegate.descendingIterator();
118   }
119 
120   @Override
descendingSet()121   public NavigableSet<E> descendingSet() {
122     return new SafeTreeSet<>(delegate.descendingSet());
123   }
124 
125   @Override
first()126   public E first() {
127     return delegate.first();
128   }
129 
130   @Override
floor(E e)131   public @Nullable E floor(E e) {
132     return delegate.floor(checkValid(e));
133   }
134 
135   @Override
headSet(E toElement)136   public SortedSet<E> headSet(E toElement) {
137     return headSet(toElement, false);
138   }
139 
140   @Override
headSet(E toElement, boolean inclusive)141   public NavigableSet<E> headSet(E toElement, boolean inclusive) {
142     return new SafeTreeSet<>(delegate.headSet(checkValid(toElement), inclusive));
143   }
144 
145   @Override
higher(E e)146   public @Nullable E higher(E e) {
147     return delegate.higher(checkValid(e));
148   }
149 
150   @Override
isEmpty()151   public boolean isEmpty() {
152     return delegate.isEmpty();
153   }
154 
155   @Override
iterator()156   public Iterator<E> iterator() {
157     return delegate.iterator();
158   }
159 
160   @Override
last()161   public E last() {
162     return delegate.last();
163   }
164 
165   @Override
lower(E e)166   public @Nullable E lower(E e) {
167     return delegate.lower(checkValid(e));
168   }
169 
170   @Override
pollFirst()171   public @Nullable E pollFirst() {
172     return delegate.pollFirst();
173   }
174 
175   @Override
pollLast()176   public @Nullable E pollLast() {
177     return delegate.pollLast();
178   }
179 
180   @Override
remove(Object object)181   public boolean remove(Object object) {
182     return delegate.remove(checkValid(object));
183   }
184 
185   @Override
removeAll(Collection<?> c)186   public boolean removeAll(Collection<?> c) {
187     return delegate.removeAll(c);
188   }
189 
190   @Override
retainAll(Collection<?> c)191   public boolean retainAll(Collection<?> c) {
192     return delegate.retainAll(c);
193   }
194 
195   @Override
size()196   public int size() {
197     return delegate.size();
198   }
199 
200   @Override
subSet( E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)201   public NavigableSet<E> subSet(
202       E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
203     return new SafeTreeSet<>(
204         delegate.subSet(
205             checkValid(fromElement), fromInclusive, checkValid(toElement), toInclusive));
206   }
207 
208   @Override
subSet(E fromElement, E toElement)209   public SortedSet<E> subSet(E fromElement, E toElement) {
210     return subSet(fromElement, true, toElement, false);
211   }
212 
213   @Override
tailSet(E fromElement)214   public SortedSet<E> tailSet(E fromElement) {
215     return tailSet(fromElement, true);
216   }
217 
218   @Override
tailSet(E fromElement, boolean inclusive)219   public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
220     return new SafeTreeSet<>(delegate.tailSet(checkValid(fromElement), inclusive));
221   }
222 
223   @Override
toArray()224   public Object[] toArray() {
225     return delegate.toArray();
226   }
227 
228   @Override
toArray(T[] a)229   public <T> T[] toArray(T[] a) {
230     return delegate.toArray(a);
231   }
232 
233   @CanIgnoreReturnValue
checkValid(T t)234   private <T> T checkValid(T t) {
235     // a ClassCastException is what's supposed to happen!
236     @SuppressWarnings("unchecked")
237     E e = (E) t;
238     int unused = comparator().compare(e, e);
239     return t;
240   }
241 
242   @Override
equals(@ullable Object obj)243   public boolean equals(@Nullable Object obj) {
244     return delegate.equals(obj);
245   }
246 
247   @Override
hashCode()248   public int hashCode() {
249     return delegate.hashCode();
250   }
251 
252   @Override
toString()253   public String toString() {
254     return delegate.toString();
255   }
256 
257   private static final long serialVersionUID = 0L;
258 }
259