001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.util.queue;
031
032import java.util.Comparator;
033import java.util.PriorityQueue;
034
035/**
036 * This class provides an inverted {@link PriorityQueue} implementation, where
037 * objects that are higher (according to the provided {@link Comparator} or the
038 * natural order) come first.
039 * <p>
040 * The Iterator provided in method {@link #iterator()} is <em>not</em>
041 * guaranteed to traverse the elements of the priority queue in any particular
042 * order.
043 * 
044 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
045 * 
046 * @param <T>
047 *            Type of objects stored in the queue
048 */
049public class InvertedPriorityQueue<T> extends PriorityQueue<T> {
050        private static final long serialVersionUID = 1L;
051
052        private static final int DEFAULT_INITIAL_CAPACITY = 11;
053
054        /**
055         * Creates a {@code InvertedPriorityQueue} with the default initial capacity
056         * (11) that orders its elements according to their inverted
057         * {@linkplain Comparable natural ordering}.
058         */
059        public InvertedPriorityQueue() {
060                super(DEFAULT_INITIAL_CAPACITY, InvertedComparableComparator.INSTANCE);
061        }
062
063        /**
064         * Creates a {@code InvertedPriorityQueue} with the specified initial
065         * capacity that orders its elements according to the inverse of the
066         * specified comparator.
067         * 
068         * @param initialCapacity
069         *            the initial capacity for this priority queue
070         * @param comparator
071         *            the comparator that will be used to order this priority queue.
072         *            If {@code null}, the {@linkplain Comparable natural ordering}
073         *            of the elements will be used. Internally, the comparator is
074         *            inverted to reverse its meaning.
075         * @throws IllegalArgumentException
076         *             if {@code initialCapacity} is less than 1
077         */
078        @SuppressWarnings("unchecked")
079        public InvertedPriorityQueue(int initialCapacity, Comparator<? super T> comparator) {
080                super(initialCapacity, comparator == null ? (Comparator<T>) InvertedComparableComparator.INSTANCE
081                                : new InvertedComparator<T>(comparator));
082        }
083
084        /**
085         * Creates a {@code InvertedPriorityQueue} with the specified initial
086         * capacity that orders its elements according to their inverse
087         * {@linkplain Comparable natural ordering}.
088         * 
089         * @param initialCapacity
090         *            the initial capacity for this priority queue
091         * @throws IllegalArgumentException
092         *             if {@code initialCapacity} is less than 1
093         */
094        public InvertedPriorityQueue(int initialCapacity) {
095                super(initialCapacity, InvertedComparableComparator.INSTANCE);
096        }
097
098        protected Comparator<? super T> originalComparator() {
099                if (comparator() instanceof InvertedComparator)
100                        return ((InvertedComparator<? super T>) comparator()).innerComparator;
101                else
102                        return ComparableComparator.INSTANCE;
103        }
104
105        /**
106         * Inverted natural order comparator.
107         * 
108         * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
109         */
110        private static class InvertedComparableComparator implements Comparator<Object> {
111                public static final InvertedComparableComparator INSTANCE = new InvertedComparableComparator();
112
113                @Override
114                @SuppressWarnings("unchecked")
115                public int compare(Object o1, Object o2) {
116                        return ((Comparable<Object>) o2).compareTo(o1);
117                }
118        }
119
120        /**
121         * Natural order comparator.
122         * 
123         * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
124         */
125        private static class ComparableComparator implements Comparator<Object> {
126                public static final ComparableComparator INSTANCE = new ComparableComparator();
127
128                @Override
129                @SuppressWarnings("unchecked")
130                public int compare(Object o1, Object o2) {
131                        return ((Comparable<Object>) o1).compareTo(o2);
132                }
133        }
134
135        /**
136         * Inverted natural order comparator.
137         * 
138         * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
139         */
140        private static class InvertedComparator<T> implements Comparator<T> {
141                protected Comparator<? super T> innerComparator;
142
143                public InvertedComparator(Comparator<? super T> innerComparator) {
144                        this.innerComparator = innerComparator;
145                }
146
147                @Override
148                public int compare(T o1, T o2) {
149                        return innerComparator.compare(o2, o1);
150                }
151        }
152}