/* * Copyright (C) 2010 The Guava Authors * * Licensed 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. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.collect.testing; import java.io.Serializable; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.NavigableSet; import java.util.SortedSet; import java.util.TreeSet; /** * A wrapper around {@code TreeSet} that aggressively checks to see if elements * are mutually comparable. This implementation passes the navigable set test * suites. * * @author Louis Wasserman */ public final class SafeTreeSet implements Serializable, NavigableSet { @SuppressWarnings("unchecked") private static final Comparator NATURAL_ORDER = new Comparator() { @Override public int compare(Object o1, Object o2) { return ((Comparable) o1).compareTo(o2); } }; private final NavigableSet delegate; public SafeTreeSet() { this(new TreeSet()); } public SafeTreeSet(Collection collection) { this(new TreeSet(collection)); } public SafeTreeSet(Comparator comparator) { this(new TreeSet(comparator)); } public SafeTreeSet(SortedSet set) { this(new TreeSet(set)); } private SafeTreeSet(NavigableSet delegate) { this.delegate = delegate; for (E e : this) { checkValid(e); } } @Override public boolean add(E element) { return delegate.add(checkValid(element)); } @Override public boolean addAll(Collection collection) { for (E e : collection) { checkValid(e); } return delegate.addAll(collection); } @Override public E ceiling(E e) { return delegate.ceiling(checkValid(e)); } @Override public void clear() { delegate.clear(); } @SuppressWarnings("unchecked") @Override public Comparator comparator() { Comparator comparator = delegate.comparator(); if (comparator == null) { comparator = (Comparator) NATURAL_ORDER; } return comparator; } @Override public boolean contains(Object object) { return delegate.contains(checkValid(object)); } @Override public boolean containsAll(Collection c) { return delegate.containsAll(c); } @Override public Iterator descendingIterator() { return delegate.descendingIterator(); } @Override public NavigableSet descendingSet() { return new SafeTreeSet(delegate.descendingSet()); } @Override public E first() { return delegate.first(); } @Override public E floor(E e) { return delegate.floor(checkValid(e)); } @Override public SortedSet headSet(E toElement) { return headSet(toElement, false); } @Override public NavigableSet headSet(E toElement, boolean inclusive) { return new SafeTreeSet( delegate.headSet(checkValid(toElement), inclusive)); } @Override public E higher(E e) { return delegate.higher(checkValid(e)); } @Override public boolean isEmpty() { return delegate.isEmpty(); } @Override public Iterator iterator() { return delegate.iterator(); } @Override public E last() { return delegate.last(); } @Override public E lower(E e) { return delegate.lower(checkValid(e)); } @Override public E pollFirst() { return delegate.pollFirst(); } @Override public E pollLast() { return delegate.pollLast(); } @Override public boolean remove(Object object) { return delegate.remove(checkValid(object)); } @Override public boolean removeAll(Collection c) { return delegate.removeAll(c); } @Override public boolean retainAll(Collection c) { return delegate.retainAll(c); } @Override public int size() { return delegate.size(); } @Override public NavigableSet subSet( E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { return new SafeTreeSet( delegate.subSet(checkValid(fromElement), fromInclusive, checkValid(toElement), toInclusive)); } @Override public SortedSet subSet(E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); } @Override public SortedSet tailSet(E fromElement) { return tailSet(fromElement, true); } @Override public NavigableSet tailSet(E fromElement, boolean inclusive) { return new SafeTreeSet(delegate.tailSet(checkValid(fromElement), inclusive)); } @Override public Object[] toArray() { return delegate.toArray(); } @Override public T[] toArray(T[] a) { return delegate.toArray(a); } private T checkValid(T t) { // a ClassCastException is what's supposed to happen! @SuppressWarnings("unchecked") E e = (E) t; comparator().compare(e, e); return t; } @Override public boolean equals(Object obj) { return delegate.equals(obj); } @Override public int hashCode() { return delegate.hashCode(); } @Override public String toString() { return delegate.toString(); } private static final long serialVersionUID = 0L; }