001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2013, 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 * HashUtilities.java
029 * ------------------
030 * (C) Copyright 2006-2013, 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
046package org.jfree.chart;
047
048import java.awt.GradientPaint;
049import java.awt.Paint;
050import java.awt.Stroke;
051
052import org.jfree.util.BooleanList;
053import org.jfree.util.PaintList;
054import org.jfree.util.StrokeList;
055
056/**
057 * Some utility methods for calculating hash codes.  
058 * 
059 * @since 1.0.3
060 */
061public 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;
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}