001/*
002 * HA-JDBC: High-Availability JDBC
003 * Copyright (C) 2012  Paul Ferraro
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Lesser General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package net.sf.hajdbc.util;
019
020import java.io.Serializable;
021import java.util.AbstractMap;
022import java.util.AbstractSet;
023import java.util.Collection;
024import java.util.Comparator;
025import java.util.Iterator;
026import java.util.NoSuchElementException;
027import java.util.Set;
028import java.util.SortedMap;
029import java.util.SortedSet;
030
031/**
032 * Collection utility methods.
033 * @author Paul Ferraro
034 */
035public class Collections
036{
037        public static final SortedSet<?> EMPTY_SORTED_SET = new EmptySortedSet<Object>();
038        public static final SortedMap<?, ?> EMPTY_SORTED_MAP = new EmptySortedMap<Object, Object>();
039        static final Iterator<?> EMPTY_ITERATOR = new EmptyIterator<Object>();
040        static final Comparator<?> NATURAL_COMPARATOR = new NaturalComparator<Object>();
041        
042        /**
043         * Returns an iterator over an empty collection.
044         * @param <E> the collection type
045         * @return a collection iterator
046         */
047        @SuppressWarnings("unchecked")
048        static <E> Iterator<E> emptyIterator()
049        {
050                return (Iterator<E>) EMPTY_ITERATOR;
051        }
052
053        /**
054         * Returns a comparator using the natural ordering of comparable objects.
055         * @param <E> the collection type
056         * @return a comparator
057         */
058        @SuppressWarnings("unchecked")
059        static <E> Comparator<E> naturalComparator()
060        {
061                return (Comparator<E>) NATURAL_COMPARATOR;
062        }
063        
064        /**
065         * Like {@link java.util.Collections#emptySet()}, but returns a sorted set.
066         * @param <E> a collection type
067         * @return an empty sorted set
068         */
069        @SuppressWarnings("unchecked")
070        public static <E> SortedSet<E> emptySortedSet()
071        {
072                return (SortedSet<E>) EMPTY_SORTED_SET;
073        }
074        
075        /**
076         * Like {@link java.util.Collections#emptyMap()}, but returns a sorted map.
077         * @param <K> the map's key type
078         * @param <V> the map's value type
079         * @return an empty sorted map
080         */
081        @SuppressWarnings("unchecked")
082        public static <K, V> SortedMap<K, V> emptySortedMap()
083        {
084                return (SortedMap<K, V>) EMPTY_SORTED_MAP;
085        }
086        
087        /**
088         * Like {@link java.util.Collections#singleton(Object)}, but returns a sorted set.
089         * @param <E>
090         * @param element
091         * @return a sorted set containing the single element.
092         */
093        public static <E> SortedSet<E> singletonSortedSet(E element)
094        {
095                return new SingletonSortedSet<E>(element);
096        }
097        
098        /**
099         * Like {@link java.util.Collections#singletonMap(Object, Object)}, but returns a sorted map.
100         * @param <K>
101         * @param <V>
102         * @param key
103         * @param value
104         * @return a sorted map containing the single key, value pair.
105         */
106        public static <K, V> SortedMap<K, V> singletonSortedMap(K key, V value)
107        {
108                return new SingletonSortedMap<K, V>(key, value);
109        }
110
111        static class NaturalComparator<E> implements Comparator<E>, Serializable
112        {
113                private static final long serialVersionUID = 984839581274651936L;
114
115                @SuppressWarnings("unchecked")
116                @Override
117                public int compare(E object1, E object2)
118                {
119                        return ((Comparable<E>) object1).compareTo(object2);
120                }
121        }
122
123        static class EmptyIterator<E> implements Iterator<E>
124        {
125                @Override
126                public boolean hasNext()
127                {
128                        return false;
129                }
130
131                @Override
132                public E next()
133                {
134                        throw new NoSuchElementException();
135                }
136
137                @Override
138                public void remove()
139                {
140                        throw new UnsupportedOperationException();
141                }
142        }
143        
144        static class EmptySortedSet<E> extends AbstractSet<E> implements SortedSet<E>, Serializable
145        {
146                private static final long serialVersionUID = 8614249160102450427L;
147
148                @Override
149                public Iterator<E> iterator()
150                {
151                        return emptyIterator();
152                }
153
154                @Override
155                public boolean contains(Object object)
156                {
157                        return false;
158                }
159
160                @Override
161                public boolean containsAll(Collection<?> c)
162                {
163                        return c.isEmpty();
164                }
165
166                @Override
167                public boolean isEmpty()
168                {
169                        return true;
170                }
171
172                @Override
173                public int size()
174                {
175                        return 0;
176                }
177
178                @Override
179                public Comparator<? super E> comparator()
180                {
181                        return null;
182                }
183
184                @Override
185                public E first()
186                {
187                        throw new NoSuchElementException();
188                }
189
190                @Override
191                public SortedSet<E> headSet(E toElement)
192                {
193                        return emptySortedSet();
194                }
195
196                @Override
197                public E last()
198                {
199                        throw new NoSuchElementException();
200                }
201
202                @Override
203                public SortedSet<E> subSet(E fromElement, E toElement)
204                {
205                        return emptySortedSet();
206                }
207
208                @Override
209                public SortedSet<E> tailSet(E fromElement)
210                {
211                        return emptySortedSet();
212                }
213        }
214        
215        static class EmptySortedMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, Serializable
216        {
217                private static final long serialVersionUID = -7955186590936566806L;
218
219                @Override
220                public boolean containsKey(Object object)
221                {
222                        return false;
223                }
224
225                @Override
226                public boolean containsValue(Object object)
227                {
228                        return false;
229                }
230
231                @Override
232                public V get(Object object)
233                {
234                        return null;
235                }
236
237                @Override
238                public boolean isEmpty()
239                {
240                        return true;
241                }
242
243                @Override
244                public Set<K> keySet()
245                {
246                        return java.util.Collections.emptySet();
247                }
248
249                @Override
250                public int size()
251                {
252                        return 0;
253                }
254
255                @Override
256                public Collection<V> values()
257                {
258                        return java.util.Collections.emptySet();
259                }
260
261                @Override
262                public Set<java.util.Map.Entry<K, V>> entrySet()
263                {
264                        return java.util.Collections.emptySet();
265                }
266
267                @Override
268                public Comparator<? super K> comparator()
269                {
270                        return null;
271                }
272
273                @Override
274                public K firstKey()
275                {
276                        throw new NoSuchElementException();
277                }
278
279                @Override
280                public SortedMap<K, V> headMap(K toKey)
281                {
282                        return emptySortedMap();
283                }
284
285                @Override
286                public K lastKey()
287                {
288                        throw new NoSuchElementException();
289                }
290
291                @Override
292                public SortedMap<K, V> subMap(K fromKey, K toKey)
293                {
294                        return emptySortedMap();
295                }
296
297                @Override
298                public SortedMap<K, V> tailMap(K fromKey)
299                {
300                        return emptySortedMap();
301                }
302        }
303        
304        static class SingletonIterator<E> implements Iterator<E>
305        {
306                private final E element;
307                private boolean hasNext = true;
308                
309                SingletonIterator(E element)
310                {
311                        this.element = element;
312                }
313                
314                @Override
315                public boolean hasNext()
316                {
317                        return this.hasNext;
318                }
319
320                @Override
321                public E next()
322                {
323                        if (!this.hasNext)
324                        {
325                                throw new NoSuchElementException();
326                        }
327
328                        this.hasNext = false;
329                        
330                        return this.element;
331                }
332
333                @Override
334                public void remove()
335                {
336                        throw new UnsupportedOperationException();
337                }
338        }
339        
340        static class NullComparator<E> implements Comparator<E>, Serializable
341        {
342                private static final long serialVersionUID = -8178822438438191299L;
343
344                @Override
345                public int compare(E object1, E object2)
346                {
347                        return 0;
348                }
349        }
350        
351        static class SingletonSortedSet<E> extends AbstractSet<E> implements SortedSet<E>, Serializable
352        {
353                private static final long serialVersionUID = -7831170170325623175L;
354                
355                private final E element;
356                
357                SingletonSortedSet(E element)
358                {
359                        this.element = element;
360                }
361
362                @Override
363                public Iterator<E> iterator()
364                {
365                        return new SingletonIterator<E>(this.element);
366                }
367
368                @Override
369                public int size()
370                {
371                        return 1;
372                }
373
374                @Override
375                public boolean contains(Object object)
376                {
377                        return this.element.equals(object);
378                }
379
380                @Override
381                public boolean isEmpty()
382                {
383                        return false;
384                }
385
386                @Override
387                public Comparator<? super E> comparator()
388                {
389                        return null;
390                }
391
392                @Override
393                public E first()
394                {
395                        return this.element;
396                }
397
398                @Override
399                public SortedSet<E> headSet(E toElement)
400                {
401                        return (naturalComparator().compare(this.element, toElement) < 0) ? this : Collections.<E>emptySortedSet();
402                }
403
404                @Override
405                public E last()
406                {
407                        return this.element;
408                }
409
410                @Override
411                public SortedSet<E> subSet(E fromElement, E toElement)
412                {
413                        Comparator<E> comparator = naturalComparator();
414                        
415                        return ((comparator.compare(this.element, toElement) < 0) && (comparator.compare(this.element, fromElement) >= 0)) ? this : Collections.<E>emptySortedSet();
416                }
417
418                @Override
419                public SortedSet<E> tailSet(E fromElement)
420                {
421                        return (naturalComparator().compare(this.element, fromElement) >= 0) ? this : Collections.<E>emptySortedSet();
422                }
423        }
424        
425        static class SingletonSortedMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, Serializable
426        {
427                private static final long serialVersionUID = -3229163217706447957L;
428                
429                private final Entry<K, V> entry;
430                
431                SingletonSortedMap(K key, V value)
432                {
433                        this.entry = new SimpleImmutableEntry<K, V>(key, value);
434                }
435
436                @Override
437                public boolean containsKey(Object object)
438                {
439                        return this.entry.getKey().equals(object);
440                }
441
442                @Override
443                public boolean containsValue(Object object)
444                {
445                        return this.entry.getValue().equals(object);
446                }
447
448                @Override
449                public V get(Object object)
450                {
451                        return this.entry.getKey().equals(object) ? this.entry.getValue() : null;
452                }
453
454                @Override
455                public boolean isEmpty()
456                {
457                        return false;
458                }
459
460                @Override
461                public Set<K> keySet()
462                {
463                        return java.util.Collections.singleton(this.entry.getKey());
464                }
465
466                @Override
467                public int size()
468                {
469                        return 1;
470                }
471
472                @Override
473                public Collection<V> values()
474                {
475                        return java.util.Collections.singleton(this.entry.getValue());
476                }
477
478                @Override
479                public Set<java.util.Map.Entry<K, V>> entrySet()
480                {
481                        return java.util.Collections.singleton(this.entry);
482                }
483
484                @Override
485                public Comparator<? super K> comparator()
486                {
487                        return null;
488                }
489
490                @Override
491                public K firstKey()
492                {
493                        return this.entry.getKey();
494                }
495
496                @Override
497                public SortedMap<K, V> headMap(K toKey)
498                {
499                        return (naturalComparator().compare(this.entry.getKey(), toKey) < 0) ? this : Collections.<K, V>emptySortedMap();
500                }
501
502                @Override
503                public K lastKey()
504                {
505                        return this.entry.getKey();
506                }
507
508                @Override
509                public SortedMap<K, V> subMap(K fromKey, K toKey)
510                {
511                        Comparator<K> comparator = naturalComparator();
512                        
513                        return ((comparator.compare(this.entry.getKey(), toKey) < 0) && (comparator.compare(this.entry.getKey(), fromKey) >= 0)) ? this : Collections.<K, V>emptySortedMap();
514                }
515
516                @Override
517                public SortedMap<K, V> tailMap(K fromKey)
518                {
519                        return (naturalComparator().compare(this.entry.getKey(), fromKey) >= 0) ? this : Collections.<K, V>emptySortedMap();
520                }
521        }
522        
523        private Collections()
524        {
525                // Hide constructor
526        }
527}