/* * HA-JDBC: High-Availability JDBC * Copyright (C) 2012 Paul Ferraro * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.hajdbc.util; import java.io.Serializable; import java.util.AbstractMap; import java.util.AbstractSet; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; /** * Collection utility methods. * @author Paul Ferraro */ public class Collections { public static final SortedSet<?> EMPTY_SORTED_SET = new EmptySortedSet<>(); public static final SortedMap<?, ?> EMPTY_SORTED_MAP = new EmptySortedMap<>(); static final Iterator<?> EMPTY_ITERATOR = new EmptyIterator<>(); static final Comparator<?> NATURAL_COMPARATOR = new NaturalComparator<>(); /** * Returns an iterator over an empty collection. * @param <E> the collection type * @return a collection iterator */ @SuppressWarnings("unchecked") static <E> Iterator<E> emptyIterator() { return (Iterator<E>) EMPTY_ITERATOR; } /** * Returns a comparator using the natural ordering of comparable objects. * @param <E> the collection type * @return a comparator */ @SuppressWarnings("unchecked") static <E> Comparator<E> naturalComparator() { return (Comparator<E>) NATURAL_COMPARATOR; } /** * Like {@link java.util.Collections#emptySet()}, but returns a sorted set. * @param <E> a collection type * @return an empty sorted set */ @SuppressWarnings("unchecked") public static <E> SortedSet<E> emptySortedSet() { return (SortedSet<E>) EMPTY_SORTED_SET; } /** * Like {@link java.util.Collections#emptyMap()}, but returns a sorted map. * @param <K> the map's key type * @param <V> the map's value type * @return an empty sorted map */ @SuppressWarnings("unchecked") public static <K, V> SortedMap<K, V> emptySortedMap() { return (SortedMap<K, V>) EMPTY_SORTED_MAP; } /** * Like {@link java.util.Collections#singleton(Object)}, but returns a sorted set. * @param <E> * @param element * @return a sorted set containing the single element. */ public static <E> SortedSet<E> singletonSortedSet(E element) { return new SingletonSortedSet<>(element); } /** * Like {@link java.util.Collections#singletonMap(Object, Object)}, but returns a sorted map. * @param <K> * @param <V> * @param key * @param value * @return a sorted map containing the single key, value pair. */ public static <K, V> SortedMap<K, V> singletonSortedMap(K key, V value) { return new SingletonSortedMap<>(key, value); } static class NaturalComparator<E> implements Comparator<E>, Serializable { private static final long serialVersionUID = 984839581274651936L; @SuppressWarnings("unchecked") @Override public int compare(E object1, E object2) { return ((Comparable<E>) object1).compareTo(object2); } } static class EmptyIterator<E> implements Iterator<E> { @Override public boolean hasNext() { return false; } @Override public E next() { throw new NoSuchElementException(); } @Override public void remove() { throw new UnsupportedOperationException(); } } static class EmptySortedSet<E> extends AbstractSet<E> implements SortedSet<E>, Serializable { private static final long serialVersionUID = 8614249160102450427L; @Override public Iterator<E> iterator() { return emptyIterator(); } @Override public boolean contains(Object object) { return false; } @Override public boolean containsAll(Collection<?> c) { return c.isEmpty(); } @Override public boolean isEmpty() { return true; } @Override public int size() { return 0; } @Override public Comparator<? super E> comparator() { return null; } @Override public E first() { throw new NoSuchElementException(); } @Override public SortedSet<E> headSet(E toElement) { return emptySortedSet(); } @Override public E last() { throw new NoSuchElementException(); } @Override public SortedSet<E> subSet(E fromElement, E toElement) { return emptySortedSet(); } @Override public SortedSet<E> tailSet(E fromElement) { return emptySortedSet(); } } static class EmptySortedMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, Serializable { private static final long serialVersionUID = -7955186590936566806L; @Override public boolean containsKey(Object object) { return false; } @Override public boolean containsValue(Object object) { return false; } @Override public V get(Object object) { return null; } @Override public boolean isEmpty() { return true; } @Override public Set<K> keySet() { return java.util.Collections.emptySet(); } @Override public int size() { return 0; } @Override public Collection<V> values() { return java.util.Collections.emptySet(); } @Override public Set<java.util.Map.Entry<K, V>> entrySet() { return java.util.Collections.emptySet(); } @Override public Comparator<? super K> comparator() { return null; } @Override public K firstKey() { throw new NoSuchElementException(); } @Override public SortedMap<K, V> headMap(K toKey) { return emptySortedMap(); } @Override public K lastKey() { throw new NoSuchElementException(); } @Override public SortedMap<K, V> subMap(K fromKey, K toKey) { return emptySortedMap(); } @Override public SortedMap<K, V> tailMap(K fromKey) { return emptySortedMap(); } } static class SingletonIterator<E> implements Iterator<E> { private final E element; private boolean hasNext = true; SingletonIterator(E element) { this.element = element; } @Override public boolean hasNext() { return this.hasNext; } @Override public E next() { if (!this.hasNext) { throw new NoSuchElementException(); } this.hasNext = false; return this.element; } @Override public void remove() { throw new UnsupportedOperationException(); } } static class NullComparator<E> implements Comparator<E>, Serializable { private static final long serialVersionUID = -8178822438438191299L; @Override public int compare(E object1, E object2) { return 0; } } static class SingletonSortedSet<E> extends AbstractSet<E> implements SortedSet<E>, Serializable { private static final long serialVersionUID = -7831170170325623175L; private final E element; SingletonSortedSet(E element) { this.element = element; } @Override public Iterator<E> iterator() { return new SingletonIterator<>(this.element); } @Override public int size() { return 1; } @Override public boolean contains(Object object) { return this.element.equals(object); } @Override public boolean isEmpty() { return false; } @Override public Comparator<? super E> comparator() { return null; } @Override public E first() { return this.element; } @Override public SortedSet<E> headSet(E toElement) { return (naturalComparator().compare(this.element, toElement) < 0) ? this : Collections.<E>emptySortedSet(); } @Override public E last() { return this.element; } @Override public SortedSet<E> subSet(E fromElement, E toElement) { Comparator<E> comparator = naturalComparator(); return ((comparator.compare(this.element, toElement) < 0) && (comparator.compare(this.element, fromElement) >= 0)) ? this : Collections.<E>emptySortedSet(); } @Override public SortedSet<E> tailSet(E fromElement) { return (naturalComparator().compare(this.element, fromElement) >= 0) ? this : Collections.<E>emptySortedSet(); } } static class SingletonSortedMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, Serializable { private static final long serialVersionUID = -3229163217706447957L; private final Entry<K, V> entry; SingletonSortedMap(K key, V value) { this.entry = new SimpleImmutableEntry<>(key, value); } @Override public boolean containsKey(Object object) { return this.entry.getKey().equals(object); } @Override public boolean containsValue(Object object) { return this.entry.getValue().equals(object); } @Override public V get(Object object) { return this.entry.getKey().equals(object) ? this.entry.getValue() : null; } @Override public boolean isEmpty() { return false; } @Override public Set<K> keySet() { return java.util.Collections.singleton(this.entry.getKey()); } @Override public int size() { return 1; } @Override public Collection<V> values() { return java.util.Collections.singleton(this.entry.getValue()); } @Override public Set<java.util.Map.Entry<K, V>> entrySet() { return java.util.Collections.singleton(this.entry); } @Override public Comparator<? super K> comparator() { return null; } @Override public K firstKey() { return this.entry.getKey(); } @Override public SortedMap<K, V> headMap(K toKey) { return (naturalComparator().compare(this.entry.getKey(), toKey) < 0) ? this : Collections.<K, V>emptySortedMap(); } @Override public K lastKey() { return this.entry.getKey(); } @Override public SortedMap<K, V> subMap(K fromKey, K toKey) { Comparator<K> comparator = naturalComparator(); return ((comparator.compare(this.entry.getKey(), toKey) < 0) && (comparator.compare(this.entry.getKey(), fromKey) >= 0)) ? this : Collections.<K, V>emptySortedMap(); } @Override public SortedMap<K, V> tailMap(K fromKey) { return (naturalComparator().compare(this.entry.getKey(), fromKey) >= 0) ? this : Collections.<K, V>emptySortedMap(); } } private Collections() { // Hide constructor } }