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