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#equals(Object)} methods.</p>
  60. *
  61. * <p> This class provides methods to build a good equals method for any
  62. * class. It follows rules laid out in
  63. * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
  64. * , by Joshua Bloch. In particular the rule for comparing <code>doubles</code>,
  65. * <code>floats</code>, and arrays can be tricky. Also, making sure that
  66. * <code>equals()</code> and <code>hashCode()</code> are consistent can be
  67. * difficult.</p>
  68. *
  69. * <p>Two Objects that compare as equals must generate the same hash code,
  70. * but two Objects with the same hash code do not have to be equal.</p>
  71. *
  72. * <p>All relevant fields should be included in the calculation of equals.
  73. * Derived fields may be ignored. In particular, any field used in
  74. * generating a hash code must be used in the equals method, and vice
  75. * versa.</p>
  76. *
  77. * <p>Typical use for the code is as follows:</p>
  78. * <pre>
  79. * public boolean equals(Object o) {
  80. * if ( !(o instanceof MyClass) ) {
  81. * return false;
  82. * }
  83. * MyClass rhs = (MyClass) o;
  84. * return new EqualsBuilder()
  85. * .appendSuper(super.equals(o))
  86. * .append(field1, rhs.field1)
  87. * .append(field2, rhs.field2)
  88. * .append(field3, rhs.field3)
  89. * .isEquals();
  90. * }
  91. * </pre>
  92. *
  93. * <p> Alternatively, there is a method that uses reflection to determine
  94. * the fields to test. Because these fields are usually private, the method,
  95. * <code>reflectionEquals</code>, uses <code>AccessibleObject.setAccessible</code> to
  96. * change the visibility of the fields. This will fail under a security
  97. * manager, unless the appropriate permissions are set up correctly. It is
  98. * also slower than testing explicitly.</p>
  99. *
  100. * <p> A typical invocation for this method would look like:</p>
  101. * <pre>
  102. * public boolean equals(Object o) {
  103. * return EqualsBuilder.reflectionEquals(this, o);
  104. * }
  105. * </pre>
  106. *
  107. * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
  108. * @author Stephen Colebourne
  109. * @author Gary Gregory
  110. * @author Pete Gieser
  111. * @since 1.0
  112. * @version $Id: EqualsBuilder.java,v 1.20 2003/08/23 00:21:49 ggregory Exp $
  113. */
  114. public class EqualsBuilder {
  115. /**
  116. * If the fields tested are equals.
  117. */
  118. private boolean isEquals;
  119. /**
  120. * <p>Constructor for EqualsBuilder.</p>
  121. *
  122. * <p>Starts off assuming that equals is <code>true</code>.</p>
  123. * @see java.lang.Object#equals
  124. */
  125. public EqualsBuilder() {
  126. super();
  127. isEquals = true;
  128. }
  129. //-------------------------------------------------------------------------
  130. /**
  131. * <p>This method uses reflection to determine if the two <code>Object</code>s
  132. * are equal.</p>
  133. *
  134. * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
  135. * fields. This means that it will throw a security exception if run under
  136. * a security manager, if the permissions are not set up correctly. It is also
  137. * not as efficient as testing explicitly.</p>
  138. *
  139. * <p>Transient members will be not be tested, as they are likely derived
  140. * fields, and not part of the value of the Object.</p>
  141. *
  142. * <p>Static fields will not be tested. Superclass fields will be included.</p>
  143. *
  144. * @param lhs <code>this</code> object
  145. * @param rhs the other object
  146. * @return <code>true</code> if the two Objects have tested equals.
  147. */
  148. public static boolean reflectionEquals(Object lhs, Object rhs) {
  149. return reflectionEquals(lhs, rhs, false, null);
  150. }
  151. /**
  152. * <p>This method uses reflection to determine if the two <code>Object</code>s
  153. * are equal.</p>
  154. *
  155. * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
  156. * fields. This means that it will throw a security exception if run under
  157. * a security manager, if the permissions are not set up correctly. It is also
  158. * not as efficient as testing explicitly.</p>
  159. *
  160. * <p>If the TestTransients parameter is set to <code>true</code>, transient
  161. * members will be tested, otherwise they are ignored, as they are likely
  162. * derived fields, and not part of the value of the <code>Object</code>.</p>
  163. *
  164. * <p>Static fields will not be tested. Superclass fields will be included.</p>
  165. *
  166. * @param lhs <code>this</code> object
  167. * @param rhs the other object
  168. * @param testTransients whether to include transient fields
  169. * @return <code>true</code> if the two Objects have tested equals.
  170. */
  171. public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients) {
  172. return reflectionEquals(lhs, rhs, testTransients, null);
  173. }
  174. /**
  175. * <p>This method uses reflection to determine if the two <code>Object</code>s
  176. * are equal.</p>
  177. *
  178. * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
  179. * fields. This means that it will throw a security exception if run under
  180. * a security manager, if the permissions are not set up correctly. It is also
  181. * not as efficient as testing explicitly.</p>
  182. *
  183. * <p>If the testTransients parameter is set to <code>true</code>, transient
  184. * members will be tested, otherwise they are ignored, as they are likely
  185. * derived fields, and not part of the value of the <code>Object</code>.</p>
  186. *
  187. * <p>Static fields will not be included. Superclass fields will be appended
  188. * up to and including the specified superclass. A null superclass is treated
  189. * as java.lang.Object.</p>
  190. *
  191. * @param lhs <code>this</code> object
  192. * @param rhs the other object
  193. * @param testTransients whether to include transient fields
  194. * @param reflectUpToClass the superclass to reflect up to (inclusive),
  195. * may be <code>null</code>
  196. * @return <code>true</code> if the two Objects have tested equals.
  197. * @since 2.0
  198. */
  199. public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) {
  200. if (lhs == rhs) {
  201. return true;
  202. }
  203. if (lhs == null || rhs == null) {
  204. return false;
  205. }
  206. // Find the leaf class since there may be transients in the leaf
  207. // class or in classes between the leaf and root.
  208. // If we are not testing transients or a subclass has no ivars,
  209. // then a subclass can test equals to a superclass.
  210. Class lhsClass = lhs.getClass();
  211. Class rhsClass = rhs.getClass();
  212. Class testClass;
  213. if (lhsClass.isInstance(rhs)) {
  214. testClass = lhsClass;
  215. if (!rhsClass.isInstance(lhs)) {
  216. // rhsClass is a subclass of lhsClass
  217. testClass = rhsClass;
  218. }
  219. } else if (rhsClass.isInstance(lhs)) {
  220. testClass = rhsClass;
  221. if (!lhsClass.isInstance(rhs)) {
  222. // lhsClass is a subclass of rhsClass
  223. testClass = lhsClass;
  224. }
  225. } else {
  226. // The two classes are not related.
  227. return false;
  228. }
  229. EqualsBuilder equalsBuilder = new EqualsBuilder();
  230. try {
  231. reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
  232. while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
  233. testClass = testClass.getSuperclass();
  234. reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
  235. }
  236. } catch (IllegalArgumentException e) {
  237. // In this case, we tried to test a subclass vs. a superclass and
  238. // the subclass has ivars or the ivars are transient and
  239. // we are testing transients.
  240. // If a subclass has ivars that we are trying to test them, we get an
  241. // exception and we know that the objects are not equal.
  242. return false;
  243. }
  244. return equalsBuilder.isEquals();
  245. }
  246. /**
  247. * <p>Appends the fields and values defined by the given object of the
  248. * given Class.</p>
  249. *
  250. * @param lhs the left hand object
  251. * @param rhs the right hand object
  252. * @param clazz the class to append details of
  253. * @param builder the builder to append to
  254. * @param useTransients whether to test transient fields
  255. */
  256. private static void reflectionAppend(
  257. Object lhs,
  258. Object rhs,
  259. Class clazz,
  260. EqualsBuilder builder,
  261. boolean useTransients) {
  262. Field[] fields = clazz.getDeclaredFields();
  263. AccessibleObject.setAccessible(fields, true);
  264. for (int i = 0; i < fields.length && builder.isEquals; i++) {
  265. Field f = fields[i];
  266. if ((f.getName().indexOf('$') == -1)
  267. && (useTransients || !Modifier.isTransient(f.getModifiers()))
  268. && (!Modifier.isStatic(f.getModifiers()))) {
  269. try {
  270. builder.append(f.get(lhs), f.get(rhs));
  271. } catch (IllegalAccessException e) {
  272. //this can't happen. Would get a Security exception instead
  273. //throw a runtime exception in case the impossible happens.
  274. throw new InternalError("Unexpected IllegalAccessException");
  275. }
  276. }
  277. }
  278. }
  279. //-------------------------------------------------------------------------
  280. /**
  281. * <p>Adds the result of <code>super.equals()</code> to this builder.</p>
  282. *
  283. * @param superEquals the result of calling <code>super.equals()</code>
  284. * @return EqualsBuilder - used to chain calls.
  285. * @since 2.0
  286. */
  287. public EqualsBuilder appendSuper(boolean superEquals) {
  288. if (isEquals == false) {
  289. return this;
  290. }
  291. isEquals = superEquals;
  292. return this;
  293. }
  294. //-------------------------------------------------------------------------
  295. /**
  296. * <p>Test if two <code>Object</code>s are equal using their
  297. * <code>equals</code> method.</p>
  298. *
  299. * @param lhs the left hand object
  300. * @param rhs the right hand object
  301. * @return EqualsBuilder - used to chain calls.
  302. */
  303. public EqualsBuilder append(Object lhs, Object rhs) {
  304. if (isEquals == false) {
  305. return this;
  306. }
  307. if (lhs == rhs) {
  308. return this;
  309. }
  310. if (lhs == null || rhs == null) {
  311. isEquals = false;
  312. return this;
  313. }
  314. Class lhsClass = lhs.getClass();
  315. if (!lhsClass.isArray()) {
  316. //the simple case, not an array, just test the element
  317. isEquals = lhs.equals(rhs);
  318. } else {
  319. //'Switch' on type of array, to dispatch to the correct handler
  320. // This handles multi dimensional arrays
  321. if (lhs instanceof long[]) {
  322. append((long[]) lhs, (long[]) rhs);
  323. } else if (lhs instanceof int[]) {
  324. append((int[]) lhs, (int[]) rhs);
  325. } else if (lhs instanceof short[]) {
  326. append((short[]) lhs, (short[]) rhs);
  327. } else if (lhs instanceof char[]) {
  328. append((char[]) lhs, (char[]) rhs);
  329. } else if (lhs instanceof byte[]) {
  330. append((byte[]) lhs, (byte[]) rhs);
  331. } else if (lhs instanceof double[]) {
  332. append((double[]) lhs, (double[]) rhs);
  333. } else if (lhs instanceof float[]) {
  334. append((float[]) lhs, (float[]) rhs);
  335. } else if (lhs instanceof boolean[]) {
  336. append((boolean[]) lhs, (boolean[]) rhs);
  337. } else {
  338. // Not an array of primitives
  339. append((Object[]) lhs, (Object[]) rhs);
  340. }
  341. }
  342. return this;
  343. }
  344. /**
  345. * <p>Test if two <code>long</code>s are equal.</p>
  346. *
  347. * @param lhs the left hand <code>long</code>
  348. * @param rhs the right hand <code>long</code>
  349. * @return EqualsBuilder - used to chain calls.
  350. */
  351. public EqualsBuilder append(long lhs, long rhs) {
  352. if (isEquals == false) {
  353. return this;
  354. }
  355. isEquals = (lhs == rhs);
  356. return this;
  357. }
  358. /**
  359. * <p>Test if two <code>int</code>s are equal.</p>
  360. *
  361. * @param lhs the left hand <code>int</code>
  362. * @param rhs the right hand <code>int</code>
  363. * @return EqualsBuilder - used to chain calls.
  364. */
  365. public EqualsBuilder append(int lhs, int rhs) {
  366. if (isEquals == false) {
  367. return this;
  368. }
  369. isEquals = (lhs == rhs);
  370. return this;
  371. }
  372. /**
  373. * <p>Test if two <code>short</code>s are equal.</p>
  374. *
  375. * @param lhs the left hand <code>short</code>
  376. * @param rhs the right hand <code>short</code>
  377. * @return EqualsBuilder - used to chain calls.
  378. */
  379. public EqualsBuilder append(short lhs, short rhs) {
  380. if (isEquals == false) {
  381. return this;
  382. }
  383. isEquals = (lhs == rhs);
  384. return this;
  385. }
  386. /**
  387. * <p>Test if two <code>char</code>s are equal.</p>
  388. *
  389. * @param lhs the left hand <code>char</code>
  390. * @param rhs the right hand <code>char</code>
  391. * @return EqualsBuilder - used to chain calls.
  392. */
  393. public EqualsBuilder append(char lhs, char rhs) {
  394. if (isEquals == false) {
  395. return this;
  396. }
  397. isEquals = (lhs == rhs);
  398. return this;
  399. }
  400. /**
  401. * <p>Test if two <code>byte</code>s are equal.</p>
  402. *
  403. * @param lhs the left hand <code>byte</code>
  404. * @param rhs the right hand <code>byte</code>
  405. * @return EqualsBuilder - used to chain calls.
  406. */
  407. public EqualsBuilder append(byte lhs, byte rhs) {
  408. if (isEquals == false) {
  409. return this;
  410. }
  411. isEquals = (lhs == rhs);
  412. return this;
  413. }
  414. /**
  415. * <p>Test if two <code>double</code>s are equal by testing that the
  416. * pattern of bits returned by <code>doubleToLong</code> are equal.</p>
  417. *
  418. * <p>This handles NaNs, Infinties, and <code>-0.0</code>.</p>
  419. *
  420. * <p>It is compatible with the hash code generated by
  421. * <code>HashCodeBuilder</code>.</p>
  422. *
  423. * @param lhs the left hand <code>double</code>
  424. * @param rhs the right hand <code>double</code>
  425. * @return EqualsBuilder - used to chain calls.
  426. */
  427. public EqualsBuilder append(double lhs, double rhs) {
  428. if (isEquals == false) {
  429. return this;
  430. }
  431. return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs));
  432. }
  433. /**
  434. * <p>Test if two <code>float</code>s are equal byt testing that the
  435. * pattern of bits returned by doubleToLong are equal.</p>
  436. *
  437. * <p>This handles NaNs, Infinties, and <code>-0.0</code>.</p>
  438. *
  439. * <p>It is compatible with the hash code generated by
  440. * <code>HashCodeBuilder</code>.</p>
  441. *
  442. * @param lhs the left hand <code>float</code>
  443. * @param rhs the right hand <code>float</code>
  444. * @return EqualsBuilder - used to chain calls.
  445. */
  446. public EqualsBuilder append(float lhs, float rhs) {
  447. if (isEquals == false) {
  448. return this;
  449. }
  450. return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs));
  451. }
  452. /**
  453. * <p>Test if two <code>booleans</code>s are equal.</p>
  454. *
  455. * @param lhs the left hand <code>boolean</code>
  456. * @param rhs the right hand <code>boolean</code>
  457. * @return EqualsBuilder - used to chain calls.
  458. */
  459. public EqualsBuilder append(boolean lhs, boolean rhs) {
  460. if (isEquals == false) {
  461. return this;
  462. }
  463. isEquals = (lhs == rhs);
  464. return this;
  465. }
  466. /**
  467. * <p>Performs a deep comparison of two <code>Object</code> arrays.</p>
  468. *
  469. * <p>This also will be called for the top level of
  470. * multi-dimensional, ragged, and multi-typed arrays.</p>
  471. *
  472. * @param lhs the left hand <code>Object[]</code>
  473. * @param rhs the right hand <code>Object[]</code>
  474. * @return EqualsBuilder - used to chain calls.
  475. */
  476. public EqualsBuilder append(Object[] lhs, Object[] rhs) {
  477. if (isEquals == false) {
  478. return this;
  479. }
  480. if (lhs == rhs) {
  481. return this;
  482. }
  483. if (lhs == null || rhs == null) {
  484. isEquals = false;
  485. return this;
  486. }
  487. if (lhs.length != rhs.length) {
  488. isEquals = false;
  489. return this;
  490. }
  491. for (int i = 0; i < lhs.length && isEquals; ++i) {
  492. Class lhsClass = lhs[i].getClass();
  493. if (!lhsClass.isInstance(rhs[i])) {
  494. isEquals = false; //If the types don't match, not equal
  495. break;
  496. }
  497. append(lhs[i], rhs[i]);
  498. }
  499. return this;
  500. }
  501. /**
  502. * <p>Deep comparison of array of <code>long</code>. Length and all
  503. * values are compared.</p>
  504. *
  505. * <p>The method {@link #append(long, long)} is used.</p>
  506. *
  507. * @param lhs the left hand <code>long[]</code>
  508. * @param rhs the right hand <code>long[]</code>
  509. * @return EqualsBuilder - used to chain calls.
  510. */
  511. public EqualsBuilder append(long[] lhs, long[] rhs) {
  512. if (isEquals == false) {
  513. return this;
  514. }
  515. if (lhs == rhs) {
  516. return this;
  517. }
  518. if (lhs == null || rhs == null) {
  519. isEquals = false;
  520. return this;
  521. }
  522. if (lhs.length != rhs.length) {
  523. isEquals = false;
  524. return this;
  525. }
  526. for (int i = 0; i < lhs.length && isEquals; ++i) {
  527. append(lhs[i], rhs[i]);
  528. }
  529. return this;
  530. }
  531. /**
  532. * <p>Deep comparison of array of <code>int</code>. Length and all
  533. * values are compared.</p>
  534. *
  535. * <p>The method {@link #append(int, int)} is used.</p>
  536. *
  537. * @param lhs the left hand <code>int[]</code>
  538. * @param rhs the right hand <code>int[]</code>
  539. * @return EqualsBuilder - used to chain calls.
  540. */
  541. public EqualsBuilder append(int[] lhs, int[] rhs) {
  542. if (isEquals == false) {
  543. return this;
  544. }
  545. if (lhs == rhs) {
  546. return this;
  547. }
  548. if (lhs == null || rhs == null) {
  549. isEquals = false;
  550. return this;
  551. }
  552. if (lhs.length != rhs.length) {
  553. isEquals = false;
  554. return this;
  555. }
  556. for (int i = 0; i < lhs.length && isEquals; ++i) {
  557. append(lhs[i], rhs[i]);
  558. }
  559. return this;
  560. }
  561. /**
  562. * <p>Deep comparison of array of <code>short</code>. Length and all
  563. * values are compared.</p>
  564. *
  565. * <p>The method {@link #append(short, short)} is used.</p>
  566. *
  567. * @param lhs the left hand <code>short[]</code>
  568. * @param rhs the right hand <code>short[]</code>
  569. * @return EqualsBuilder - used to chain calls.
  570. */
  571. public EqualsBuilder append(short[] lhs, short[] rhs) {
  572. if (isEquals == false) {
  573. return this;
  574. }
  575. if (lhs == rhs) {
  576. return this;
  577. }
  578. if (lhs == null || rhs == null) {
  579. isEquals = false;
  580. return this;
  581. }
  582. if (lhs.length != rhs.length) {
  583. isEquals = false;
  584. return this;
  585. }
  586. for (int i = 0; i < lhs.length && isEquals; ++i) {
  587. append(lhs[i], rhs[i]);
  588. }
  589. return this;
  590. }
  591. /**
  592. * <p>Deep comparison of array of <code>char</code>. Length and all
  593. * values are compared.</p>
  594. *
  595. * <p>The method {@link #append(char, char)} is used.</p>
  596. *
  597. * @param lhs the left hand <code>char[]</code>
  598. * @param rhs the right hand <code>char[]</code>
  599. * @return EqualsBuilder - used to chain calls.
  600. */
  601. public EqualsBuilder append(char[] lhs, char[] rhs) {
  602. if (isEquals == false) {
  603. return this;
  604. }
  605. if (lhs == rhs) {
  606. return this;
  607. }
  608. if (lhs == null || rhs == null) {
  609. isEquals = false;
  610. return this;
  611. }
  612. if (lhs.length != rhs.length) {
  613. isEquals = false;
  614. return this;
  615. }
  616. for (int i = 0; i < lhs.length && isEquals; ++i) {
  617. append(lhs[i], rhs[i]);
  618. }
  619. return this;
  620. }
  621. /**
  622. * <p>Deep comparison of array of <code>byte</code>. Length and all
  623. * values are compared.</p>
  624. *
  625. * <p>The method {@link #append(byte, byte)} is used.</p>
  626. *
  627. * @param lhs the left hand <code>byte[]</code>
  628. * @param rhs the right hand <code>byte[]</code>
  629. * @return EqualsBuilder - used to chain calls.
  630. */
  631. public EqualsBuilder append(byte[] lhs, byte[] rhs) {
  632. if (isEquals == false) {
  633. return this;
  634. }
  635. if (lhs == rhs) {
  636. return this;
  637. }
  638. if (lhs == null || rhs == null) {
  639. isEquals = false;
  640. return this;
  641. }
  642. if (lhs.length != rhs.length) {
  643. isEquals = false;
  644. return this;
  645. }
  646. for (int i = 0; i < lhs.length && isEquals; ++i) {
  647. append(lhs[i], rhs[i]);
  648. }
  649. return this;
  650. }
  651. /**
  652. * <p>Deep comparison of array of <code>double</code>. Length and all
  653. * values are compared.</p>
  654. *
  655. * <p>The method {@link #append(double, double)} is used.</p>
  656. *
  657. * @param lhs the left hand <code>double[]</code>
  658. * @param rhs the right hand <code>double[]</code>
  659. * @return EqualsBuilder - used to chain calls.
  660. */
  661. public EqualsBuilder append(double[] lhs, double[] rhs) {
  662. if (isEquals == false) {
  663. return this;
  664. }
  665. if (lhs == rhs) {
  666. return this;
  667. }
  668. if (lhs == null || rhs == null) {
  669. isEquals = false;
  670. return this;
  671. }
  672. if (lhs.length != rhs.length) {
  673. isEquals = false;
  674. return this;
  675. }
  676. for (int i = 0; i < lhs.length && isEquals; ++i) {
  677. append(lhs[i], rhs[i]);
  678. }
  679. return this;
  680. }
  681. /**
  682. * <p>Deep comparison of array of <code>float</code>. Length and all
  683. * values are compared.</p>
  684. *
  685. * <p>The method {@link #append(float, float)} is used.</p>
  686. *
  687. * @param lhs the left hand <code>float[]</code>
  688. * @param rhs the right hand <code>float[]</code>
  689. * @return EqualsBuilder - used to chain calls.
  690. */
  691. public EqualsBuilder append(float[] lhs, float[] rhs) {
  692. if (isEquals == false) {
  693. return this;
  694. }
  695. if (lhs == rhs) {
  696. return this;
  697. }
  698. if (lhs == null || rhs == null) {
  699. isEquals = false;
  700. return this;
  701. }
  702. if (lhs.length != rhs.length) {
  703. isEquals = false;
  704. return this;
  705. }
  706. for (int i = 0; i < lhs.length && isEquals; ++i) {
  707. append(lhs[i], rhs[i]);
  708. }
  709. return this;
  710. }
  711. /**
  712. * <p>Deep comparison of array of <code>boolean</code>. Length and all
  713. * values are compared.</p>
  714. *
  715. * <p>The method {@link #append(boolean, boolean)} is used.</p>
  716. *
  717. * @param lhs the left hand <code>boolean[]</code>
  718. * @param rhs the right hand <code>boolean[]</code>
  719. * @return EqualsBuilder - used to chain calls.
  720. */
  721. public EqualsBuilder append(boolean[] lhs, boolean[] rhs) {
  722. if (isEquals == false) {
  723. return this;
  724. }
  725. if (lhs == rhs) {
  726. return this;
  727. }
  728. if (lhs == null || rhs == null) {
  729. isEquals = false;
  730. return this;
  731. }
  732. if (lhs.length != rhs.length) {
  733. isEquals = false;
  734. return this;
  735. }
  736. for (int i = 0; i < lhs.length && isEquals; ++i) {
  737. append(lhs[i], rhs[i]);
  738. }
  739. return this;
  740. }
  741. /**
  742. * <p>Return <code>true</code> if the fields that have been checked
  743. * are all equal.</p>
  744. *
  745. * @return boolean
  746. */
  747. public boolean isEquals() {
  748. return isEquals;
  749. }
  750. }