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 17package com.google.common.collect.testing; 18 19import java.io.Serializable; 20import java.util.Collection; 21import java.util.Comparator; 22import java.util.Iterator; 23import java.util.SortedSet; 24import java.util.TreeSet; 25 26/** 27 * A wrapper around {@code TreeSet} that aggressively checks to see if elements 28 * are mutually comparable. This implementation passes the navigable set test 29 * suites. 30 * 31 * @author Louis Wasserman 32 */ 33public final class SafeTreeSet<E> implements Serializable, SortedSet<E> { 34 @SuppressWarnings("unchecked") 35 private static final Comparator<Object> NATURAL_ORDER = new Comparator<Object>() { 36 @Override public int compare(Object o1, Object o2) { 37 return ((Comparable<Object>) o1).compareTo(o2); 38 } 39 }; 40 private final SortedSet<E> delegate; 41 42 public SafeTreeSet() { 43 this(new TreeSet<E>()); 44 } 45 46 public SafeTreeSet(Collection<? extends E> collection) { 47 this(new TreeSet<E>(collection)); 48 } 49 50 public SafeTreeSet(Comparator<? super E> comparator) { 51 this(new TreeSet<E>(comparator)); 52 } 53 54 private SafeTreeSet(SortedSet<E> delegate) { 55 this.delegate = delegate; 56 for (E e : this) { 57 checkValid(e); 58 } 59 } 60 61 @Override public boolean add(E element) { 62 return delegate.add(checkValid(element)); 63 } 64 65 @Override public boolean addAll(Collection<? extends E> collection) { 66 for (E e : collection) { 67 checkValid(e); 68 } 69 return delegate.addAll(collection); 70 } 71 72 @Override public void clear() { 73 delegate.clear(); 74 } 75 76 @SuppressWarnings("unchecked") 77 @Override public Comparator<? super E> comparator() { 78 Comparator<? super E> comparator = delegate.comparator(); 79 if (comparator == null) { 80 comparator = (Comparator<? super E>) NATURAL_ORDER; 81 } 82 return comparator; 83 } 84 85 @Override public boolean contains(Object object) { 86 return delegate.contains(checkValid(object)); 87 } 88 89 @Override public boolean containsAll(Collection<?> c) { 90 return delegate.containsAll(c); 91 } 92 93 @Override public E first() { 94 return delegate.first(); 95 } 96 97 @Override public SortedSet<E> headSet(E toElement) { 98 return new SafeTreeSet<E>(delegate.headSet(checkValid(toElement))); 99 } 100 101 @Override public boolean isEmpty() { 102 return delegate.isEmpty(); 103 } 104 105 @Override public Iterator<E> iterator() { 106 return delegate.iterator(); 107 } 108 109 @Override public E last() { 110 return delegate.last(); 111 } 112 113 @Override public boolean remove(Object object) { 114 return delegate.remove(checkValid(object)); 115 } 116 117 @Override public boolean removeAll(Collection<?> c) { 118 return delegate.removeAll(c); 119 } 120 121 @Override public boolean retainAll(Collection<?> c) { 122 return delegate.retainAll(c); 123 } 124 125 @Override public int size() { 126 return delegate.size(); 127 } 128 129 130 @Override public SortedSet<E> subSet(E fromElement, E toElement) { 131 return new SafeTreeSet<E>(delegate.subSet(checkValid(fromElement), checkValid(toElement))); 132 } 133 134 @Override public SortedSet<E> tailSet(E fromElement) { 135 return new SafeTreeSet<E>(delegate.tailSet(checkValid(fromElement))); 136 } 137 138 @Override public Object[] toArray() { 139 return delegate.toArray(); 140 } 141 142 @Override public <T> T[] toArray(T[] a) { 143 return delegate.toArray(a); 144 } 145 146 private <T> T checkValid(T t) { 147 // a ClassCastException is what's supposed to happen! 148 @SuppressWarnings("unchecked") 149 E e = (E) t; 150 comparator().compare(e, e); 151 return t; 152 } 153 154 @Override public boolean equals(Object obj) { 155 return delegate.equals(obj); 156 } 157 158 @Override public int hashCode() { 159 return delegate.hashCode(); 160 } 161 162 @Override public String toString() { 163 return delegate.toString(); 164 } 165 166 private static final long serialVersionUID = 0L; 167} 168