Fix issues related to checkstyle enforcement for module
[aaa.git] / aaa-authn / src / main / java / org / opendaylight / aaa / HashCodeUtil.java
1 /*****************************************************************************
2  * Copyright (c) 2014, 2017 Hewlett-Packard Development Company, L.P. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  *****************************************************************************/
8
9 package org.opendaylight.aaa;
10
11 import java.lang.reflect.Array;
12
13 /**
14  * Collected methods which allow easy implementation of <tt>hashCode</tt>.
15  *
16  * <p>
17  * Example use case:
18  *
19  * <pre>
20  * public int hashCode() {
21  *     int result = HashCodeUtil.SEED;
22  *     // collect the contributions of various fields
23  *     result = HashCodeUtil.hash(result, fPrimitive);
24  *     result = HashCodeUtil.hash(result, fObject);
25  *     result = HashCodeUtil.hash(result, fArray);
26  *     return result;
27  * }
28  * </pre>
29  */
30 public final class HashCodeUtil {
31
32     /**
33      * An initial value for a <tt>hashCode</tt>, to which is added contributions
34      * from fields. Using a non-zero value decreases collisions of
35      * <tt>hashCode</tt> values.
36      */
37     public static final int SEED = 23;
38
39     private HashCodeUtil() {
40     }
41
42     /** booleans. */
43     public static int hash(int seed, boolean booleanNumber) {
44         return firstTerm(seed) + (booleanNumber ? 1 : 0);
45     }
46
47     /*** chars. */
48     public static int hash(int seed, char character) {
49         return firstTerm(seed) + character;
50     }
51
52     /** ints. */
53     public static int hash(int seed, int integer) {
54         return firstTerm(seed) + integer;
55     }
56
57     /** longs. */
58     public static int hash(int seed, long longNumber) {
59         return firstTerm(seed) + (int) (longNumber ^ longNumber >>> 32);
60     }
61
62     /** floats. */
63     public static int hash(int seed, float floatNumber) {
64         return hash(seed, Float.floatToIntBits(floatNumber));
65     }
66
67     /** doubles. */
68     public static int hash(int seed, double doubleNumber) {
69         return hash(seed, Double.doubleToLongBits(doubleNumber));
70     }
71
72     /**
73      * <tt>aObject</tt> is a possibly-null object field, and possibly an array.
74      *
75      * <p>
76      * If <tt>aObject</tt> is an array, then each element may be a primitive or
77      * a possibly-null object.
78      */
79     public static int hash(int seed, Object object) {
80         int result = seed;
81         if (object == null) {
82             result = hash(result, 0);
83         } else if (!isArray(object)) {
84             result = hash(result, object.hashCode());
85         } else {
86             int length = Array.getLength(object);
87             for (int idx = 0; idx < length; ++idx) {
88                 Object item = Array.get(object, idx);
89                 // if an item in the array references the array itself, prevent
90                 // infinite looping
91                 if (!(item == object)) {
92                     result = hash(result, item);
93                 }
94             }
95         }
96         return result;
97     }
98
99     // PRIVATE
100     private static final int ODD_PRIME_NUMBER = 37;
101
102     private static int firstTerm(int seed) {
103         return ODD_PRIME_NUMBER * seed;
104     }
105
106     private static boolean isArray(Object object) {
107         return object.getClass().isArray();
108     }
109 }