    001/* ===========================================================
    002 * JFreeChart : a free chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C) Copyright 2000-2011, 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, 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
    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 = 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}