001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2007, by Object Refinery Limited 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 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * ------------------ 028 * HashUtilities.java 029 * ------------------ 030 * (C) Copyright 2006, 2007, by Object Refinery Limited; 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * Changes 036 * ------- 037 * 03-Oct-2006 : Version 1 (DG); 038 * 06-Mar-2007 : Fix for hashCodeForDoubleArray() method (DG); 039 * 13-Nov-2007 : Added new utility methods (DG); 040 * 22-Nov-2007 : Added hashCode() method for 'int' (DG); 041 * 05-Dec-2007 : Added special methods to handle BooleanList, PaintList, 042 * and StrokeList (DG); 043 * 044 */ 045 046 package org.jfree.chart; 047 048 import java.awt.GradientPaint; 049 import java.awt.Paint; 050 import java.awt.Stroke; 051 052 import org.jfree.util.BooleanList; 053 import org.jfree.util.PaintList; 054 import org.jfree.util.StrokeList; 055 056 /** 057 * Some utility methods for calculating hash codes. 058 * 059 * @since 1.0.3 060 */ 061 public class HashUtilities { 062 063 /** 064 * Returns a hash code for a <code>Paint</code> instance. If 065 * <code>p</code> is <code>null</code>, this method returns zero. 066 * 067 * @param p the paint (<code>null</code> permitted). 068 * 069 * @return The hash code. 070 */ 071 public static int hashCodeForPaint(Paint p) { 072 if (p == null) { 073 return 0; 074 } 075 int result = 0; 076 // handle GradientPaint as a special case 077 if (p instanceof GradientPaint) { 078 GradientPaint gp = (GradientPaint) p; 079 result = 193; 080 result = 37 * result + gp.getColor1().hashCode(); 081 result = 37 * result + gp.getPoint1().hashCode(); 082 result = 37 * result + gp.getColor2().hashCode(); 083 result = 37 * result + gp.getPoint2().hashCode(); 084 } 085 else { 086 // we assume that all other Paint instances implement equals() and 087 // hashCode()...of course that might not be true, but what can we 088 // do about it? 089 result = p.hashCode(); 090 } 091 return result; 092 } 093 094 /** 095 * Returns a hash code for a <code>double[]</code> instance. If the array 096 * is <code>null</code>, this method returns zero. 097 * 098 * @param a the array (<code>null</code> permitted). 099 * 100 * @return The hash code. 101 */ 102 public static int hashCodeForDoubleArray(double[] a) { 103 if (a == null) { 104 return 0; 105 } 106 int result = 193; 107 long temp; 108 for (int i = 0; i < a.length; i++) { 109 temp = Double.doubleToLongBits(a[i]); 110 result = 29 * result + (int) (temp ^ (temp >>> 32)); 111 } 112 return result; 113 } 114 115 /** 116 * Returns a hash value based on a seed value and the value of a boolean 117 * primitive. 118 * 119 * @param pre the seed value. 120 * @param b the boolean value. 121 * 122 * @return A hash value. 123 * 124 * @since 1.0.7 125 */ 126 public static int hashCode(int pre, boolean b) { 127 return 37 * pre + (b ? 0 : 1); 128 } 129 130 /** 131 * Returns a hash value based on a seed value and the value of an int 132 * primitive. 133 * 134 * @param pre the seed value. 135 * @param i the int value. 136 * 137 * @return A hash value. 138 * 139 * @since 1.0.8 140 */ 141 public static int hashCode(int pre, int i) { 142 return 37 * pre + i; 143 } 144 145 /** 146 * Returns a hash value based on a seed value and the value of a double 147 * primitive. 148 * 149 * @param pre the seed value. 150 * @param d the double value. 151 * 152 * @return A hash value. 153 * 154 * @since 1.0.7 155 */ 156 public static int hashCode(int pre, double d) { 157 long l = Double.doubleToLongBits(d); 158 return 37 * pre + (int) (l ^ (l >>> 32)); 159 } 160 161 /** 162 * Returns a hash value based on a seed value and a paint instance. 163 * 164 * @param pre the seed value. 165 * @param p the paint (<code>null</code> permitted). 166 * 167 * @return A hash value. 168 * 169 * @since 1.0.7 170 */ 171 public static int hashCode(int pre, Paint p) { 172 return 37 * pre + hashCodeForPaint(p); 173 } 174 175 /** 176 * Returns a hash value based on a seed value and a stroke instance. 177 * 178 * @param pre the seed value. 179 * @param s the stroke (<code>null</code> permitted). 180 * 181 * @return A hash value. 182 * 183 * @since 1.0.7 184 */ 185 public static int hashCode(int pre, Stroke s) { 186 int h = (s != null ? s.hashCode() : 0); 187 return 37 * pre + h; 188 } 189 190 /** 191 * Returns a hash value based on a seed value and a string instance. 192 * 193 * @param pre the seed value. 194 * @param s the string (<code>null</code> permitted). 195 * 196 * @return A hash value. 197 * 198 * @since 1.0.7 199 */ 200 public static int hashCode(int pre, String s) { 201 int h = (s != null ? s.hashCode() : 0); 202 return 37 * pre + h; 203 } 204 205 /** 206 * Returns a hash value based on a seed value and a <code>Comparable</code> 207 * instance. 208 * 209 * @param pre the seed value. 210 * @param c the comparable (<code>null</code> permitted). 211 * 212 * @return A hash value. 213 * 214 * @since 1.0.7 215 */ 216 public static int hashCode(int pre, Comparable c) { 217 int h = (c != null ? c.hashCode() : 0); 218 return 37 * pre + h; 219 } 220 221 /** 222 * Returns a hash value based on a seed value and an <code>Object</code> 223 * instance. 224 * 225 * @param pre the seed value. 226 * @param obj the object (<code>null</code> permitted). 227 * 228 * @return A hash value. 229 * 230 * @since 1.0.8 231 */ 232 public static int hashCode(int pre, Object obj) { 233 int h = (obj != null ? obj.hashCode() : 0); 234 return 37 * pre + h; 235 } 236 237 /** 238 * Computes a hash code for a {@link BooleanList}. In the latest version 239 * of JCommon, the {@link BooleanList} class should implement the hashCode() 240 * method correctly, but we compute it here anyway so that we can work with 241 * older versions of JCommon (back to 1.0.0). 242 * 243 * @param pre the seed value. 244 * @param list the list (<code>null</code> permitted). 245 * 246 * @return The hash code. 247 * 248 * @since 1.0.9 249 */ 250 public static int hashCode(int pre, BooleanList list) { 251 if (list == null) { 252 return pre; 253 } 254 int result = 127; 255 int size = list.size(); 256 result = HashUtilities.hashCode(result, size); 257 258 // for efficiency, we just use the first, last and middle items to 259 // compute a hashCode... 260 if (size > 0) { 261 result = HashUtilities.hashCode(result, list.getBoolean(0)); 262 if (size > 1) { 263 result = HashUtilities.hashCode(result, 264 list.getBoolean(size - 1)); 265 if (size > 2) { 266 result = HashUtilities.hashCode(result, 267 list.getBoolean(size / 2)); 268 } 269 } 270 } 271 return 37 * pre + result; 272 } 273 274 /** 275 * Computes a hash code for a {@link PaintList}. In the latest version 276 * of JCommon, the {@link PaintList} class should implement the hashCode() 277 * method correctly, but we compute it here anyway so that we can work with 278 * older versions of JCommon (back to 1.0.0). 279 * 280 * @param pre the seed value. 281 * @param list the list (<code>null</code> permitted). 282 * 283 * @return The hash code. 284 * 285 * @since 1.0.9 286 */ 287 public static int hashCode(int pre, PaintList list) { 288 if (list == null) { 289 return pre; 290 } 291 int result = 127; 292 int size = list.size(); 293 result = HashUtilities.hashCode(result, size); 294 295 // for efficiency, we just use the first, last and middle items to 296 // compute a hashCode... 297 if (size > 0) { 298 result = HashUtilities.hashCode(result, list.getPaint(0)); 299 if (size > 1) { 300 result = HashUtilities.hashCode(result, 301 list.getPaint(size - 1)); 302 if (size > 2) { 303 result = HashUtilities.hashCode(result, 304 list.getPaint(size / 2)); 305 } 306 } 307 } 308 return 37 * pre + result; 309 } 310 311 /** 312 * Computes a hash code for a {@link StrokeList}. In the latest version 313 * of JCommon, the {@link StrokeList} class should implement the hashCode() 314 * method correctly, but we compute it here anyway so that we can work with 315 * older versions of JCommon (back to 1.0.0). 316 * 317 * @param pre the seed value. 318 * @param list the list (<code>null</code> permitted). 319 * 320 * @return The hash code. 321 * 322 * @since 1.0.9 323 */ 324 public static int hashCode(int pre, StrokeList list) { 325 if (list == null) { 326 return pre; 327 } 328 int result = 127; 329 int size = list.size(); 330 result = HashUtilities.hashCode(result, size); 331 332 // for efficiency, we just use the first, last and middle items to 333 // compute a hashCode... 334 if (size > 0) { 335 result = HashUtilities.hashCode(result, list.getStroke(0)); 336 if (size > 1) { 337 result = HashUtilities.hashCode(result, 338 list.getStroke(size - 1)); 339 if (size > 2) { 340 result = HashUtilities.hashCode(result, 341 list.getStroke(size / 2)); 342 } 343 } 344 } 345 return 37 * pre + result; 346 } 347 }