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 }