1. /* ====================================================================
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowledgement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowledgement may appear in the software itself,
  24. * if and wherever such third-party acknowledgements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Commons", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Software Foundation.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.commons.lang.builder;
  55. import java.lang.reflect.AccessibleObject;
  56. import java.lang.reflect.Field;
  57. import java.lang.reflect.Modifier;
  58. /**
  59. * <p>Assists in implementing {@link Object#hashCode()} methods.</p>
  60. *
  61. * <p> This class enables a good <code>hashCode</code> method to be built for any class. It
  62. * follows the rules laid out in the book
  63. * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
  64. * by Joshua Bloch. Writing a good <code>hashCode</code> method is actually quite
  65. * difficult. This class aims to simplify the process.</p>
  66. *
  67. * <p>All relevant fields from the object should be included in the
  68. * <code>hashCode</code> method. Derived fields may be excluded. In general, any
  69. * field used in the <code>equals</code> method must be used in the <code>hashCode</code>
  70. * method.</p>
  71. *
  72. * <p>To use this class write code as follows:</p>
  73. * <pre>
  74. * public class Person {
  75. * String name;
  76. * int age;
  77. * boolean isSmoker;
  78. * ...
  79. *
  80. * public int hashCode() {
  81. * // you pick a hard-coded, randomly chosen, non-zero, odd number
  82. * // ideally different for each class
  83. * return new HashCodeBuilder(17, 37).
  84. * append(name).
  85. * append(age).
  86. * append(smoker).
  87. * toHashCode();
  88. * }
  89. * }
  90. * </pre>
  91. *
  92. * <p>If required, the superclass <code>hashCode()</code> can be added
  93. * using {@link #appendSuper}.</p>
  94. *
  95. * <p>Alternatively, there is a method that uses reflection to determine
  96. * the fields to test. Because these fields are usually private, the method,
  97. * <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code> to
  98. * change the visibility of the fields. This will fail under a security manager,
  99. * unless the appropriate permissions are set up correctly. It is also slower
  100. * than testing explicitly.</p>
  101. *
  102. * <p>A typical invocation for this method would look like:</p>
  103. * <pre>
  104. * public int hashCode() {
  105. * return HashCodeBuilder.reflectionHashCode(this);
  106. * }
  107. * </pre>
  108. *
  109. * @author Stephen Colebourne
  110. * @author Gary Gregory
  111. * @author Pete Gieser
  112. * @since 1.0
  113. * @version $Id: HashCodeBuilder.java,v 1.20 2003/08/23 00:21:49 ggregory Exp $
  114. */
  115. public class HashCodeBuilder {
  116. /**
  117. * Constant to use in building the hashCode.
  118. */
  119. private final int iConstant;
  120. /**
  121. * Running total of the hashCode.
  122. */
  123. private int iTotal = 0;
  124. /**
  125. * <p>Constructor.</p>
  126. *
  127. * <p>This constructor uses two hard coded choices for the constants
  128. * needed to build a <code>hashCode</code>.</p>
  129. */
  130. public HashCodeBuilder() {
  131. super();
  132. iConstant = 37;
  133. iTotal = 17;
  134. }
  135. /**
  136. * <p>Constructor.</p>
  137. *
  138. * <p>Two randomly chosen, non-zero, odd numbers must be passed in.
  139. * Ideally these should be different for each class, however this is
  140. * not vital.</p>
  141. *
  142. * <p>Prime numbers are preferred, especially for the multiplier.</p>
  143. *
  144. * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
  145. * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
  146. * @throws IllegalArgumentException if the number is zero or even
  147. */
  148. public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
  149. super();
  150. if (initialNonZeroOddNumber == 0) {
  151. throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
  152. }
  153. if (initialNonZeroOddNumber % 2 == 0) {
  154. throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
  155. }
  156. if (multiplierNonZeroOddNumber == 0) {
  157. throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
  158. }
  159. if (multiplierNonZeroOddNumber % 2 == 0) {
  160. throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
  161. }
  162. iConstant = multiplierNonZeroOddNumber;
  163. iTotal = initialNonZeroOddNumber;
  164. }
  165. //-------------------------------------------------------------------------
  166. /**
  167. * <p>This method uses reflection to build a valid hash code.</p>
  168. *
  169. * <p>This constructor uses two hard coded choices for the constants
  170. * needed to build a hash code.</p>
  171. *
  172. * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
  173. * fields. This means that it will throw a security exception if run under
  174. * a security manager, if the permissions are not set up correctly. It is
  175. * also not as efficient as testing explicitly.</p>
  176. *
  177. * <p>Transient members will be not be used, as they are likely derived
  178. * fields, and not part of the value of the <code>Object</code>.</p>
  179. *
  180. * <p>Static fields will not be tested. Superclass fields will be included.</p>
  181. *
  182. * @param object the Object to create a <code>hashCode</code> for
  183. * @return int hash code
  184. * @throws IllegalArgumentException if the object is <code>null</code>
  185. */
  186. public static int reflectionHashCode(Object object) {
  187. return reflectionHashCode(17, 37, object, false, null);
  188. }
  189. /**
  190. * <p>This method uses reflection to build a valid hash code.</p>
  191. *
  192. * <p>This constructor uses two hard coded choices for the constants needed
  193. * to build a hash code.</p>
  194. *
  195. * <p> It uses <code>AccessibleObject.setAccessible</code> to gain access to private
  196. * fields. This means that it will throw a security exception if run under
  197. * a security manager, if the permissions are not set up correctly. It is
  198. * also not as efficient as testing explicitly.</p>
  199. *
  200. * <P>If the TestTransients parameter is set to <code>true</code>, transient
  201. * members will be tested, otherwise they are ignored, as they are likely
  202. * derived fields, and not part of the value of the <code>Object</code>.</p>
  203. *
  204. * <p>Static fields will not be tested. Superclass fields will be included.</p>
  205. *
  206. * @param object the Object to create a <code>hashCode</code> for
  207. * @param testTransients whether to include transient fields
  208. * @return int hash code
  209. * @throws IllegalArgumentException if the object is <code>null</code>
  210. */
  211. public static int reflectionHashCode(Object object, boolean testTransients) {
  212. return reflectionHashCode(17, 37, object, testTransients, null);
  213. }
  214. /**
  215. * <p>This method uses reflection to build a valid hash code.</p>
  216. *
  217. * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
  218. * fields. This means that it will throw a security exception if run under
  219. * a security manager, if the permissions are not set up correctly. It is
  220. * also not as efficient as testing explicitly.</p>
  221. *
  222. * <p>Transient members will be not be used, as they are likely derived
  223. * fields, and not part of the value of the <code>Object</code>.</p>
  224. *
  225. * <p>Static fields will not be tested. Superclass fields will be included.</p>
  226. *
  227. * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
  228. * these should be different for each class, however this is not vital.
  229. * Prime numbers are preferred, especially for the multiplier.</p>
  230. *
  231. * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
  232. * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
  233. * @param object the Object to create a <code>hashCode</code> for
  234. * @return int hash code
  235. * @throws IllegalArgumentException if the Object is <code>null</code>
  236. * @throws IllegalArgumentException if the number is zero or even
  237. */
  238. public static int reflectionHashCode(
  239. int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object) {
  240. return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
  241. }
  242. /**
  243. * <p>This method uses reflection to build a valid hash code.</p>
  244. *
  245. * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
  246. * fields. This means that it will throw a security exception if run under
  247. * a security manager, if the permissions are not set up correctly. It is also
  248. * not as efficient as testing explicitly.</p>
  249. *
  250. * <p>If the TestTransients parameter is set to <code>true</code>, transient
  251. * members will be tested, otherwise they are ignored, as they are likely
  252. * derived fields, and not part of the value of the <code>Object</code>.</p>
  253. *
  254. * <p>Static fields will not be tested. Superclass fields will be included.</p>
  255. *
  256. * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
  257. * these should be different for each class, however this is not vital.
  258. * Prime numbers are preferred, especially for the multiplier.</p>
  259. *
  260. * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
  261. * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
  262. * @param object the Object to create a <code>hashCode</code> for
  263. * @param testTransients whether to include transient fields
  264. * @return int hash code
  265. * @throws IllegalArgumentException if the Object is <code>null</code>
  266. * @throws IllegalArgumentException if the number is zero or even
  267. */
  268. public static int reflectionHashCode(
  269. int initialNonZeroOddNumber, int multiplierNonZeroOddNumber,
  270. Object object, boolean testTransients) {
  271. return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
  272. }
  273. /**
  274. * <p>This method uses reflection to build a valid hash code.</p>
  275. *
  276. * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
  277. * fields. This means that it will throw a security exception if run under
  278. * a security manager, if the permissions are not set up correctly. It is also
  279. * not as efficient as testing explicitly.</p>
  280. *
  281. * <p>If the TestTransients parameter is set to <code>true</code>, transient
  282. * members will be tested, otherwise they are ignored, as they are likely
  283. * derived fields, and not part of the value of the <code>Object</code>.</p>
  284. *
  285. * <p>Static fields will not be included. Superclass fields will be included
  286. * up to and including the specified superclass. A null superclass is treated
  287. * as java.lang.Object.</p>
  288. *
  289. * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
  290. * these should be different for each class, however this is not vital.
  291. * Prime numbers are preferred, especially for the multiplier.</p>
  292. *
  293. * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
  294. * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
  295. * @param object the Object to create a <code>hashCode</code> for
  296. * @param testTransients whether to include transient fields
  297. * @param reflectUpToClass the superclass to reflect up to (inclusive),
  298. * may be <code>null</code>
  299. * @return int hash code
  300. * @throws IllegalArgumentException if the Object is <code>null</code>
  301. * @throws IllegalArgumentException if the number is zero or even
  302. * @since 2.0
  303. */
  304. public static int reflectionHashCode(
  305. int initialNonZeroOddNumber,
  306. int multiplierNonZeroOddNumber,
  307. Object object,
  308. boolean testTransients,
  309. Class reflectUpToClass) {
  310. if (object == null) {
  311. throw new IllegalArgumentException("The object to build a hash code for must not be null");
  312. }
  313. HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
  314. Class clazz = object.getClass();
  315. reflectionAppend(object, clazz, builder, testTransients);
  316. while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
  317. clazz = clazz.getSuperclass();
  318. reflectionAppend(object, clazz, builder, testTransients);
  319. }
  320. return builder.toHashCode();
  321. }
  322. /**
  323. * <p>Appends the fields and values defined by the given object of the
  324. * given <code>Class</code>.</p>
  325. *
  326. * @param object the object to append details of
  327. * @param clazz the class to append details of
  328. * @param builder the builder to append to
  329. * @param useTransients whether to use transient fields
  330. */
  331. private static void reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients) {
  332. Field[] fields = clazz.getDeclaredFields();
  333. AccessibleObject.setAccessible(fields, true);
  334. for (int i = 0; i < fields.length; i++) {
  335. Field f = fields[i];
  336. if ((f.getName().indexOf('$') == -1)
  337. && (useTransients || !Modifier.isTransient(f.getModifiers()))
  338. && (!Modifier.isStatic(f.getModifiers()))) {
  339. try {
  340. builder.append(f.get(object));
  341. } catch (IllegalAccessException e) {
  342. //this can't happen. Would get a Security exception instead
  343. //throw a runtime exception in case the impossible happens.
  344. throw new InternalError("Unexpected IllegalAccessException");
  345. }
  346. }
  347. }
  348. }
  349. //-------------------------------------------------------------------------
  350. /**
  351. * <p>Adds the result of super.hashCode() to this builder.</p>
  352. *
  353. * @param superHashCode the result of calling <code>super.hashCode()</code>
  354. * @return this HashCodeBuilder, used to chain calls.
  355. * @since 2.0
  356. */
  357. public HashCodeBuilder appendSuper(int superHashCode) {
  358. iTotal = iTotal * iConstant + superHashCode;
  359. return this;
  360. }
  361. //-------------------------------------------------------------------------
  362. /**
  363. * <p>Append a <code>hashCode</code> for an <code>Object</code>.</p>
  364. *
  365. * @param object the Object to add to the <code>hashCode</code>
  366. * @return this
  367. */
  368. public HashCodeBuilder append(Object object) {
  369. if (object == null) {
  370. iTotal = iTotal * iConstant;
  371. } else {
  372. if (object.getClass().isArray() == false) {
  373. //the simple case, not an array, just the element
  374. iTotal = iTotal * iConstant + object.hashCode();
  375. } else {
  376. //'Switch' on type of array, to dispatch to the correct handler
  377. // This handles multi dimensional arrays
  378. if (object instanceof long[]) {
  379. append((long[]) object);
  380. } else if (object instanceof int[]) {
  381. append((int[]) object);
  382. } else if (object instanceof short[]) {
  383. append((short[]) object);
  384. } else if (object instanceof char[]) {
  385. append((char[]) object);
  386. } else if (object instanceof byte[]) {
  387. append((byte[]) object);
  388. } else if (object instanceof double[]) {
  389. append((double[]) object);
  390. } else if (object instanceof float[]) {
  391. append((float[]) object);
  392. } else if (object instanceof boolean[]) {
  393. append((boolean[]) object);
  394. } else {
  395. // Not an array of primitives
  396. append((Object[]) object);
  397. }
  398. }
  399. }
  400. return this;
  401. }
  402. /**
  403. * <p>Append a <code>hashCode</code> for a <code>long</code>.</p>
  404. *
  405. * @param value the long to add to the <code>hashCode</code>
  406. * @return this
  407. */
  408. public HashCodeBuilder append(long value) {
  409. iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
  410. return this;
  411. }
  412. /**
  413. * <p>Append a <code>hashCode</code> for an <code>int</code>.</p>
  414. *
  415. * @param value the int to add to the <code>hashCode</code>
  416. * @return this
  417. */
  418. public HashCodeBuilder append(int value) {
  419. iTotal = iTotal * iConstant + value;
  420. return this;
  421. }
  422. /**
  423. * <p>Append a <code>hashCode</code> for a <code>short</code>.</p>
  424. *
  425. * @param value the short to add to the <code>hashCode</code>
  426. * @return this
  427. */
  428. public HashCodeBuilder append(short value) {
  429. iTotal = iTotal * iConstant + value;
  430. return this;
  431. }
  432. /**
  433. * <p>Append a <code>hashCode</code> for a <code>char</code>.</p>
  434. *
  435. * @param value the char to add to the <code>hashCode</code>
  436. * @return this
  437. */
  438. public HashCodeBuilder append(char value) {
  439. iTotal = iTotal * iConstant + value;
  440. return this;
  441. }
  442. /**
  443. * <p>Append a <code>hashCode</code> for a <code>byte</code>.</p>
  444. *
  445. * @param value the byte to add to the <code>hashCode</code>
  446. * @return this
  447. */
  448. public HashCodeBuilder append(byte value) {
  449. iTotal = iTotal * iConstant + value;
  450. return this;
  451. }
  452. /**
  453. * <p>Append a <code>hashCode</code> for a <code>double</code>.</p>
  454. *
  455. * @param value the double to add to the <code>hashCode</code>
  456. * @return this
  457. */
  458. public HashCodeBuilder append(double value) {
  459. return append(Double.doubleToLongBits(value));
  460. }
  461. /**
  462. * <p>Append a <code>hashCode</code> for a <code>float</code>.</p>
  463. *
  464. * @param value the float to add to the <code>hashCode</code>
  465. * @return this
  466. */
  467. public HashCodeBuilder append(float value) {
  468. iTotal = iTotal * iConstant + Float.floatToIntBits(value);
  469. return this;
  470. }
  471. /**
  472. * <p>Append a <code>hashCode</code> for a <code>boolean</code>.</p>
  473. *
  474. * @param value the boolean to add to the <code>hashCode</code>
  475. * @return this
  476. */
  477. public HashCodeBuilder append(boolean value) {
  478. iTotal = iTotal * iConstant + (value ? 0 : 1);
  479. return this;
  480. }
  481. /**
  482. * <p>Append a <code>hashCode</code> for an <code>Object</code> array.</p>
  483. *
  484. * @param array the array to add to the <code>hashCode</code>
  485. * @return this
  486. */
  487. public HashCodeBuilder append(Object[] array) {
  488. if (array == null) {
  489. iTotal = iTotal * iConstant;
  490. } else {
  491. for (int i = 0; i < array.length; i++) {
  492. append(array[i]);
  493. }
  494. }
  495. return this;
  496. }
  497. /**
  498. * <p>Append a <code>hashCode</code> for a <code>long</code> array.</p>
  499. *
  500. * @param array the array to add to the <code>hashCode</code>
  501. * @return this
  502. */
  503. public HashCodeBuilder append(long[] array) {
  504. if (array == null) {
  505. iTotal = iTotal * iConstant;
  506. } else {
  507. for (int i = 0; i < array.length; i++) {
  508. append(array[i]);
  509. }
  510. }
  511. return this;
  512. }
  513. /**
  514. * <p>Append a <code>hashCode</code> for an <code>int</code> array.</p>
  515. *
  516. * @param array the array to add to the <code>hashCode</code>
  517. * @return this
  518. */
  519. public HashCodeBuilder append(int[] array) {
  520. if (array == null) {
  521. iTotal = iTotal * iConstant;
  522. } else {
  523. for (int i = 0; i < array.length; i++) {
  524. append(array[i]);
  525. }
  526. }
  527. return this;
  528. }
  529. /**
  530. * <p>Append a <code>hashCode</code> for a <code>short</code> array.</p>
  531. *
  532. * @param array the array to add to the <code>hashCode</code>
  533. * @return this
  534. */
  535. public HashCodeBuilder append(short[] array) {
  536. if (array == null) {
  537. iTotal = iTotal * iConstant;
  538. } else {
  539. for (int i = 0; i < array.length; i++) {
  540. append(array[i]);
  541. }
  542. }
  543. return this;
  544. }
  545. /**
  546. * <p>Append a <code>hashCode</code> for a <code>char</code> array.</p>
  547. *
  548. * @param array the array to add to the <code>hashCode</code>
  549. * @return this
  550. */
  551. public HashCodeBuilder append(char[] array) {
  552. if (array == null) {
  553. iTotal = iTotal * iConstant;
  554. } else {
  555. for (int i = 0; i < array.length; i++) {
  556. append(array[i]);
  557. }
  558. }
  559. return this;
  560. }
  561. /**
  562. * <p>Append a <code>hashCode</code> for a <code>byte</code> array.</p>
  563. *
  564. * @param array the array to add to the <code>hashCode</code>
  565. * @return this
  566. */
  567. public HashCodeBuilder append(byte[] array) {
  568. if (array == null) {
  569. iTotal = iTotal * iConstant;
  570. } else {
  571. for (int i = 0; i < array.length; i++) {
  572. append(array[i]);
  573. }
  574. }
  575. return this;
  576. }
  577. /**
  578. * <p>Append a <code>hashCode</code> for a <code>double</code> array.</p>
  579. *
  580. * @param array the array to add to the <code>hashCode</code>
  581. * @return this
  582. */
  583. public HashCodeBuilder append(double[] array) {
  584. if (array == null) {
  585. iTotal = iTotal * iConstant;
  586. } else {
  587. for (int i = 0; i < array.length; i++) {
  588. append(array[i]);
  589. }
  590. }
  591. return this;
  592. }
  593. /**
  594. * <p>Append a <code>hashCode</code> for a <code>float</code> array.</p>
  595. *
  596. * @param array the array to add to the <code>hashCode</code>
  597. * @return this
  598. */
  599. public HashCodeBuilder append(float[] array) {
  600. if (array == null) {
  601. iTotal = iTotal * iConstant;
  602. } else {
  603. for (int i = 0; i < array.length; i++) {
  604. append(array[i]);
  605. }
  606. }
  607. return this;
  608. }
  609. /**
  610. * <p>Append a <code>hashCode</code> for a <code>boolean</code> array.</p>
  611. *
  612. * @param array the array to add to the <code>hashCode</code>
  613. * @return this
  614. */
  615. public HashCodeBuilder append(boolean[] array) {
  616. if (array == null) {
  617. iTotal = iTotal * iConstant;
  618. } else {
  619. for (int i = 0; i < array.length; i++) {
  620. append(array[i]);
  621. }
  622. }
  623. return this;
  624. }
  625. /**
  626. * <p>Return the computed <code>hashCode</code>.</p>
  627. *
  628. * @return <code>hashCode</code> based on the fields appended
  629. */
  630. public int toHashCode() {
  631. return iTotal;
  632. }
  633. }