001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-present, by David Gilbert and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * -------------- 028 * HashUtils.java 029 * -------------- 030 * (C) Copyright 2006-present, by David Gilbert; 031 * 032 * Original Author: David Gilbert; 033 * Contributor(s): -; 034 * 035 */ 036 037package org.jfree.chart; 038 039import java.awt.GradientPaint; 040import java.awt.Paint; 041import java.awt.Stroke; 042import org.jfree.chart.util.BooleanList; 043import org.jfree.chart.util.PaintList; 044import org.jfree.chart.util.StrokeList; 045 046/** 047 * Some utility methods for calculating hash codes. 048 */ 049public class HashUtils { 050 051 /** 052 * Returns a hash code for a {@code Paint} instance. If 053 * {@code p} is {@code null}, this method returns zero. 054 * 055 * @param p the paint ({@code null} permitted). 056 * 057 * @return The hash code. 058 */ 059 public static int hashCodeForPaint(Paint p) { 060 if (p == null) { 061 return 0; 062 } 063 int result; 064 // handle GradientPaint as a special case 065 if (p instanceof GradientPaint) { 066 GradientPaint gp = (GradientPaint) p; 067 result = 193; 068 result = 37 * result + gp.getColor1().hashCode(); 069 result = 37 * result + gp.getPoint1().hashCode(); 070 result = 37 * result + gp.getColor2().hashCode(); 071 result = 37 * result + gp.getPoint2().hashCode(); 072 } 073 else { 074 // we assume that all other Paint instances implement equals() and 075 // hashCode()...of course that might not be true, but what can we 076 // do about it? 077 result = p.hashCode(); 078 } 079 return result; 080 } 081 082 /** 083 * Returns a hash code for a {@code double[]} instance. If the array 084 * is {@code null}, this method returns zero. 085 * 086 * @param a the array ({@code null} permitted). 087 * 088 * @return The hash code. 089 */ 090 public static int hashCodeForDoubleArray(double[] a) { 091 if (a == null) { 092 return 0; 093 } 094 int result = 193; 095 long temp; 096 for (int i = 0; i < a.length; i++) { 097 temp = Double.doubleToLongBits(a[i]); 098 result = 29 * result + (int) (temp ^ (temp >>> 32)); 099 } 100 return result; 101 } 102 103 /** 104 * Returns a hash value based on a seed value and the value of a boolean 105 * primitive. 106 * 107 * @param pre the seed value. 108 * @param b the boolean value. 109 * 110 * @return A hash value. 111 */ 112 public static int hashCode(int pre, boolean b) { 113 return 37 * pre + (b ? 0 : 1); 114 } 115 116 /** 117 * Returns a hash value based on a seed value and the value of an int 118 * primitive. 119 * 120 * @param pre the seed value. 121 * @param i the int value. 122 * 123 * @return A hash value. 124 */ 125 public static int hashCode(int pre, int i) { 126 return 37 * pre + i; 127 } 128 129 /** 130 * Returns a hash value based on a seed value and the value of a double 131 * primitive. 132 * 133 * @param pre the seed value. 134 * @param d the double value. 135 * 136 * @return A hash value. 137 */ 138 public static int hashCode(int pre, double d) { 139 long l = Double.doubleToLongBits(d); 140 return 37 * pre + (int) (l ^ (l >>> 32)); 141 } 142 143 /** 144 * Returns a hash value based on a seed value and a paint instance. 145 * 146 * @param pre the seed value. 147 * @param p the paint ({@code null} permitted). 148 * 149 * @return A hash value. 150 */ 151 public static int hashCode(int pre, Paint p) { 152 return 37 * pre + hashCodeForPaint(p); 153 } 154 155 /** 156 * Returns a hash value based on a seed value and a stroke instance. 157 * 158 * @param pre the seed value. 159 * @param s the stroke ({@code null} permitted). 160 * 161 * @return A hash value. 162 */ 163 public static int hashCode(int pre, Stroke s) { 164 int h = (s != null ? s.hashCode() : 0); 165 return 37 * pre + h; 166 } 167 168 /** 169 * Returns a hash value based on a seed value and a string instance. 170 * 171 * @param pre the seed value. 172 * @param s the string ({@code null} permitted). 173 * 174 * @return A hash value. 175 */ 176 public static int hashCode(int pre, String s) { 177 int h = (s != null ? s.hashCode() : 0); 178 return 37 * pre + h; 179 } 180 181 /** 182 * Returns a hash value based on a seed value and a {@code Comparable} 183 * instance. 184 * 185 * @param pre the seed value. 186 * @param c the comparable ({@code null} permitted). 187 * 188 * @return A hash value. 189 */ 190 public static int hashCode(int pre, Comparable c) { 191 int h = (c != null ? c.hashCode() : 0); 192 return 37 * pre + h; 193 } 194 195 /** 196 * Returns a hash value based on a seed value and an {@code Object} 197 * instance. 198 * 199 * @param pre the seed value. 200 * @param obj the object ({@code null} permitted). 201 * 202 * @return A hash value. 203 */ 204 public static int hashCode(int pre, Object obj) { 205 int h = (obj != null ? obj.hashCode() : 0); 206 return 37 * pre + h; 207 } 208 209 /** 210 * Computes a hash code for a {@link BooleanList}. In the latest version 211 * of JCommon, the {@link BooleanList} class should implement the hashCode() 212 * method correctly, but we compute it here anyway so that we can work with 213 * older versions of JCommon (back to 1.0.0). 214 * 215 * @param pre the seed value. 216 * @param list the list ({@code null} permitted). 217 * 218 * @return The hash code. 219 */ 220 public static int hashCode(int pre, BooleanList list) { 221 if (list == null) { 222 return pre; 223 } 224 int result = 127; 225 int size = list.size(); 226 result = HashUtils.hashCode(result, size); 227 228 // for efficiency, we just use the first, last and middle items to 229 // compute a hashCode... 230 if (size > 0) { 231 result = HashUtils.hashCode(result, list.getBoolean(0)); 232 if (size > 1) { 233 result = HashUtils.hashCode(result, 234 list.getBoolean(size - 1)); 235 if (size > 2) { 236 result = HashUtils.hashCode(result, 237 list.getBoolean(size / 2)); 238 } 239 } 240 } 241 return 37 * pre + result; 242 } 243 244 /** 245 * Computes a hash code for a {@link PaintList}. In the latest version 246 * of JCommon, the {@link PaintList} class should implement the hashCode() 247 * method correctly, but we compute it here anyway so that we can work with 248 * older versions of JCommon (back to 1.0.0). 249 * 250 * @param pre the seed value. 251 * @param list the list ({@code null} permitted). 252 * 253 * @return The hash code. 254 */ 255 public static int hashCode(int pre, PaintList list) { 256 if (list == null) { 257 return pre; 258 } 259 int result = 127; 260 int size = list.size(); 261 result = HashUtils.hashCode(result, size); 262 263 // for efficiency, we just use the first, last and middle items to 264 // compute a hashCode... 265 if (size > 0) { 266 result = HashUtils.hashCode(result, list.getPaint(0)); 267 if (size > 1) { 268 result = HashUtils.hashCode(result, 269 list.getPaint(size - 1)); 270 if (size > 2) { 271 result = HashUtils.hashCode(result, 272 list.getPaint(size / 2)); 273 } 274 } 275 } 276 return 37 * pre + result; 277 } 278 279 /** 280 * Computes a hash code for a {@link StrokeList}. In the latest version 281 * of JCommon, the {@link StrokeList} class should implement the hashCode() 282 * method correctly, but we compute it here anyway so that we can work with 283 * older versions of JCommon (back to 1.0.0). 284 * 285 * @param pre the seed value. 286 * @param list the list ({@code null} permitted). 287 * 288 * @return The hash code. 289 */ 290 public static int hashCode(int pre, StrokeList list) { 291 if (list == null) { 292 return pre; 293 } 294 int result = 127; 295 int size = list.size(); 296 result = HashUtils.hashCode(result, size); 297 298 // for efficiency, we just use the first, last and middle items to 299 // compute a hashCode... 300 if (size > 0) { 301 result = HashUtils.hashCode(result, list.getStroke(0)); 302 if (size > 1) { 303 result = HashUtils.hashCode(result, 304 list.getStroke(size - 1)); 305 if (size > 2) { 306 result = HashUtils.hashCode(result, 307 list.getStroke(size / 2)); 308 } 309 } 310 } 311 return 37 * pre + result; 312 } 313}