1 /**
2 * Copyright 2006-2016 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.mybatis.generator.internal.util;
17
18 import java.lang.reflect.Array;
19
20 /**
21 * This class is from javapractices.com:
22 *
23 * http://www.javapractices.com/Topic28.cjp
24 *
25 * Collected methods which allow easy implementation of <code>hashCode</code>.
26 *
27 * Example use case:
28 *
29 * <pre>
30 * public int hashCode() {
31 * int result = HashCodeUtil.SEED;
32 * //collect the contributions of various fields
33 * result = HashCodeUtil.hash(result, fPrimitive);
34 * result = HashCodeUtil.hash(result, fObject);
35 * result = HashCodeUtil.hash(result, fArray);
36 * return result;
37 * }
38 * </pre>
39 */
40 public final class HashCodeUtil {
41
42 /**
43 * An initial value for a <code>hashCode</code>, to which is added
44 * contributions from fields. Using a non-zero value decreases collisons of
45 * <code>hashCode</code> values.
46 */
47 public static final int SEED = 23;
48
49 /**
50 * booleans.
51 *
52 * @param aSeed
53 * the a seed
54 * @param aBoolean
55 * the a boolean
56 * @return the int
57 */
58 public static int hash(int aSeed, boolean aBoolean) {
59 return firstTerm(aSeed) + (aBoolean ? 1 : 0);
60 }
61
62 /**
63 * chars.
64 *
65 * @param aSeed
66 * the a seed
67 * @param aChar
68 * the a char
69 * @return the int
70 */
71 public static int hash(int aSeed, char aChar) {
72 return firstTerm(aSeed) + aChar;
73 }
74
75 /**
76 * ints.
77 *
78 * @param aSeed
79 * the a seed
80 * @param aInt
81 * the a int
82 * @return the int
83 */
84 public static int hash(int aSeed, int aInt) {
85 /*
86 * Implementation Note Note that byte and short are handled by this
87 * method, through implicit conversion.
88 */
89 return firstTerm(aSeed) + aInt;
90 }
91
92 /**
93 * longs.
94 *
95 * @param aSeed
96 * the a seed
97 * @param aLong
98 * the a long
99 * @return the int
100 */
101 public static int hash(int aSeed, long aLong) {
102 return firstTerm(aSeed) + (int) (aLong ^ (aLong >>> 32));
103 }
104
105 /**
106 * floats.
107 *
108 * @param aSeed
109 * the a seed
110 * @param aFloat
111 * the a float
112 * @return the int
113 */
114 public static int hash(int aSeed, float aFloat) {
115 return hash(aSeed, Float.floatToIntBits(aFloat));
116 }
117
118 /**
119 * doubles.
120 *
121 * @param aSeed
122 * the a seed
123 * @param aDouble
124 * the a double
125 * @return the int
126 */
127 public static int hash(int aSeed, double aDouble) {
128 return hash(aSeed, Double.doubleToLongBits(aDouble));
129 }
130
131 /**
132 * <code>aObject</code> is a possibly-null object field, and possibly an array.
133 *
134 * If <code>aObject</code> is an array, then each element may be a primitive or a possibly-null object.
135 *
136 * @param aSeed
137 * the a seed
138 * @param aObject
139 * the a object
140 * @return the int
141 */
142 public static int hash(int aSeed, Object aObject) {
143 int result = aSeed;
144 if (aObject == null) {
145 result = hash(result, 0);
146 } else if (!isArray(aObject)) {
147 result = hash(result, aObject.hashCode());
148 } else {
149 int length = Array.getLength(aObject);
150 for (int idx = 0; idx < length; ++idx) {
151 Object item = Array.get(aObject, idx);
152 // recursive call!
153 result = hash(result, item);
154 }
155 }
156 return result;
157 }
158
159 // / PRIVATE ///
160 /** The odd prime number. */
161 private static final int fODD_PRIME_NUMBER = 37;
162
163 /**
164 * First term.
165 *
166 * @param aSeed
167 * the a seed
168 * @return the int
169 */
170 private static int firstTerm(int aSeed) {
171 return fODD_PRIME_NUMBER * aSeed;
172 }
173
174 /**
175 * Checks if is array.
176 *
177 * @param aObject
178 * the a object
179 * @return true, if is array
180 */
181 private static boolean isArray(Object aObject) {
182 return aObject.getClass().isArray();
183 }
184 }