001/* 002 * Copyright 2002-2012 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.util.Assert; 023 024/** 025 * A decorator for a comparator, with an "ascending" flag denoting 026 * whether comparison results should be treated in forward (standard 027 * ascending) order or flipped for reverse (descending) order. 028 * 029 * @author Keith Donald 030 * @author Juergen Hoeller 031 * @since 1.2.2 032 */ 033@SuppressWarnings("serial") 034public class InvertibleComparator<T> implements Comparator<T>, Serializable { 035 036 private final Comparator<T> comparator; 037 038 private boolean ascending = true; 039 040 041 /** 042 * Create an InvertibleComparator that sorts ascending by default. 043 * For the actual comparison, the specified Comparator will be used. 044 * @param comparator the comparator to decorate 045 */ 046 public InvertibleComparator(Comparator<T> comparator) { 047 Assert.notNull(comparator, "Comparator must not be null"); 048 this.comparator = comparator; 049 } 050 051 /** 052 * Create an InvertibleComparator that sorts based on the provided order. 053 * For the actual comparison, the specified Comparator will be used. 054 * @param comparator the comparator to decorate 055 * @param ascending the sort order: ascending (true) or descending (false) 056 */ 057 public InvertibleComparator(Comparator<T> comparator, boolean ascending) { 058 Assert.notNull(comparator, "Comparator must not be null"); 059 this.comparator = comparator; 060 setAscending(ascending); 061 } 062 063 064 /** 065 * Specify the sort order: ascending (true) or descending (false). 066 */ 067 public void setAscending(boolean ascending) { 068 this.ascending = ascending; 069 } 070 071 /** 072 * Return the sort order: ascending (true) or descending (false). 073 */ 074 public boolean isAscending() { 075 return this.ascending; 076 } 077 078 /** 079 * Invert the sort order: ascending -> descending or 080 * descending -> ascending. 081 */ 082 public void invertOrder() { 083 this.ascending = !this.ascending; 084 } 085 086 087 @Override 088 public int compare(T o1, T o2) { 089 int result = this.comparator.compare(o1, o2); 090 if (result != 0) { 091 // Invert the order if it is a reverse sort. 092 if (!this.ascending) { 093 if (Integer.MIN_VALUE == result) { 094 result = Integer.MAX_VALUE; 095 } 096 else { 097 result *= -1; 098 } 099 } 100 return result; 101 } 102 return 0; 103 } 104 105 @Override 106 @SuppressWarnings("unchecked") 107 public boolean equals(Object obj) { 108 if (this == obj) { 109 return true; 110 } 111 if (!(obj instanceof InvertibleComparator)) { 112 return false; 113 } 114 InvertibleComparator<T> other = (InvertibleComparator<T>) obj; 115 return (this.comparator.equals(other.comparator) && this.ascending == other.ascending); 116 } 117 118 @Override 119 public int hashCode() { 120 return this.comparator.hashCode(); 121 } 122 123 @Override 124 public String toString() { 125 return "InvertibleComparator: [" + this.comparator + "]; ascending=" + this.ascending; 126 } 127 128}