001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.util.comparator;
018
019import java.io.Serializable;
020import java.util.Comparator;
021
022import org.springframework.lang.Nullable;
023import org.springframework.util.Assert;
024
025/**
026 * A decorator for a comparator, with an "ascending" flag denoting
027 * whether comparison results should be treated in forward (standard
028 * ascending) order or flipped for reverse (descending) order.
029 *
030 * @author Keith Donald
031 * @author Juergen Hoeller
032 * @since 1.2.2
033 * @param <T> the type of objects that may be compared by this comparator
034 * @deprecated as of Spring Framework 5.0, in favor of the standard JDK 8
035 * {@link Comparator#reversed()}
036 */
037@Deprecated
038@SuppressWarnings("serial")
039public class InvertibleComparator<T> implements Comparator<T>, Serializable {
040
041        private final Comparator<T> comparator;
042
043        private boolean ascending = true;
044
045
046        /**
047         * Create an InvertibleComparator that sorts ascending by default.
048         * For the actual comparison, the specified Comparator will be used.
049         * @param comparator the comparator to decorate
050         */
051        public InvertibleComparator(Comparator<T> comparator) {
052                Assert.notNull(comparator, "Comparator must not be null");
053                this.comparator = comparator;
054        }
055
056        /**
057         * Create an InvertibleComparator that sorts based on the provided order.
058         * For the actual comparison, the specified Comparator will be used.
059         * @param comparator the comparator to decorate
060         * @param ascending the sort order: ascending (true) or descending (false)
061         */
062        public InvertibleComparator(Comparator<T> comparator, boolean ascending) {
063                Assert.notNull(comparator, "Comparator must not be null");
064                this.comparator = comparator;
065                setAscending(ascending);
066        }
067
068
069        /**
070         * Specify the sort order: ascending (true) or descending (false).
071         */
072        public void setAscending(boolean ascending) {
073                this.ascending = ascending;
074        }
075
076        /**
077         * Return the sort order: ascending (true) or descending (false).
078         */
079        public boolean isAscending() {
080                return this.ascending;
081        }
082
083        /**
084         * Invert the sort order: ascending -> descending or
085         * descending -> ascending.
086         */
087        public void invertOrder() {
088                this.ascending = !this.ascending;
089        }
090
091
092        @Override
093        public int compare(T o1, T o2) {
094                int result = this.comparator.compare(o1, o2);
095                if (result != 0) {
096                        // Invert the order if it is a reverse sort.
097                        if (!this.ascending) {
098                                if (Integer.MIN_VALUE == result) {
099                                        result = Integer.MAX_VALUE;
100                                }
101                                else {
102                                        result *= -1;
103                                }
104                        }
105                        return result;
106                }
107                return 0;
108        }
109
110        @Override
111        @SuppressWarnings("unchecked")
112        public boolean equals(@Nullable Object other) {
113                if (this == other) {
114                        return true;
115                }
116                if (!(other instanceof InvertibleComparator)) {
117                        return false;
118                }
119                InvertibleComparator<T> otherComp = (InvertibleComparator<T>) other;
120                return (this.comparator.equals(otherComp.comparator) && this.ascending == otherComp.ascending);
121        }
122
123        @Override
124        public int hashCode() {
125                return this.comparator.hashCode();
126        }
127
128        @Override
129        public String toString() {
130                return "InvertibleComparator: [" + this.comparator + "]; ascending=" + this.ascending;
131        }
132
133}