    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    }