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.beans.support; 018 019import java.io.Serializable; 020 021import org.springframework.util.StringUtils; 022 023/** 024 * Mutable implementation of the {@link SortDefinition} interface. 025 * Supports toggling the ascending value on setting the same property again. 026 * 027 * @author Juergen Hoeller 028 * @author Jean-Pierre Pawlak 029 * @since 26.05.2003 030 * @see #setToggleAscendingOnProperty 031 */ 032@SuppressWarnings("serial") 033public class MutableSortDefinition implements SortDefinition, Serializable { 034 035 private String property = ""; 036 037 private boolean ignoreCase = true; 038 039 private boolean ascending = true; 040 041 private boolean toggleAscendingOnProperty = false; 042 043 044 /** 045 * Create an empty MutableSortDefinition, 046 * to be populated via its bean properties. 047 * @see #setProperty 048 * @see #setIgnoreCase 049 * @see #setAscending 050 */ 051 public MutableSortDefinition() { 052 } 053 054 /** 055 * Copy constructor: create a new MutableSortDefinition 056 * that mirrors the given sort definition. 057 * @param source the original sort definition 058 */ 059 public MutableSortDefinition(SortDefinition source) { 060 this.property = source.getProperty(); 061 this.ignoreCase = source.isIgnoreCase(); 062 this.ascending = source.isAscending(); 063 } 064 065 /** 066 * Create a MutableSortDefinition for the given settings. 067 * @param property the property to compare 068 * @param ignoreCase whether upper and lower case in String values should be ignored 069 * @param ascending whether to sort ascending (true) or descending (false) 070 */ 071 public MutableSortDefinition(String property, boolean ignoreCase, boolean ascending) { 072 this.property = property; 073 this.ignoreCase = ignoreCase; 074 this.ascending = ascending; 075 } 076 077 /** 078 * Create a new MutableSortDefinition. 079 * @param toggleAscendingOnSameProperty whether to toggle the ascending flag 080 * if the same property gets set again (that is, {@code setProperty} gets 081 * called with already set property name again). 082 */ 083 public MutableSortDefinition(boolean toggleAscendingOnSameProperty) { 084 this.toggleAscendingOnProperty = toggleAscendingOnSameProperty; 085 } 086 087 088 /** 089 * Set the property to compare. 090 * <p>If the property was the same as the current, the sort is reversed if 091 * "toggleAscendingOnProperty" is activated, else simply ignored. 092 * @see #setToggleAscendingOnProperty 093 */ 094 public void setProperty(String property) { 095 if (!StringUtils.hasLength(property)) { 096 this.property = ""; 097 } 098 else { 099 // Implicit toggling of ascending? 100 if (isToggleAscendingOnProperty()) { 101 this.ascending = (!property.equals(this.property) || !this.ascending); 102 } 103 this.property = property; 104 } 105 } 106 107 @Override 108 public String getProperty() { 109 return this.property; 110 } 111 112 /** 113 * Set whether upper and lower case in String values should be ignored. 114 */ 115 public void setIgnoreCase(boolean ignoreCase) { 116 this.ignoreCase = ignoreCase; 117 } 118 119 @Override 120 public boolean isIgnoreCase() { 121 return this.ignoreCase; 122 } 123 124 /** 125 * Set whether to sort ascending (true) or descending (false). 126 */ 127 public void setAscending(boolean ascending) { 128 this.ascending = ascending; 129 } 130 131 @Override 132 public boolean isAscending() { 133 return this.ascending; 134 } 135 136 /** 137 * Set whether to toggle the ascending flag if the same property gets set again 138 * (that is, {@link #setProperty} gets called with already set property name again). 139 * <p>This is particularly useful for parameter binding through a web request, 140 * where clicking on the field header again might be supposed to trigger a 141 * resort for the same field but opposite order. 142 */ 143 public void setToggleAscendingOnProperty(boolean toggleAscendingOnProperty) { 144 this.toggleAscendingOnProperty = toggleAscendingOnProperty; 145 } 146 147 /** 148 * Return whether to toggle the ascending flag if the same property gets set again 149 * (that is, {@code setProperty} gets called with already set property name again). 150 */ 151 public boolean isToggleAscendingOnProperty() { 152 return this.toggleAscendingOnProperty; 153 } 154 155 156 @Override 157 public boolean equals(Object other) { 158 if (this == other) { 159 return true; 160 } 161 if (!(other instanceof SortDefinition)) { 162 return false; 163 } 164 SortDefinition otherSd = (SortDefinition) other; 165 return (getProperty().equals(otherSd.getProperty()) && 166 isAscending() == otherSd.isAscending() && 167 isIgnoreCase() == otherSd.isIgnoreCase()); 168 } 169 170 @Override 171 public int hashCode() { 172 int hashCode = getProperty().hashCode(); 173 hashCode = 29 * hashCode + (isIgnoreCase() ? 1 : 0); 174 hashCode = 29 * hashCode + (isAscending() ? 1 : 0); 175 return hashCode; 176 } 177 178}