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. import java.util.Comparator;
  59. import org.apache.commons.lang.math.NumberUtils;
  60. /**
  61. * Assists in implementing {@link java.lang.Comparable#compareTo(Object)} methods.
  62. *
  63. * It is consistent with <code>equals(Object)</code> and
  64. * <code>hashcode()</code> built with {@link EqualsBuilder} and
  65. * {@link HashCodeBuilder}.</p>
  66. *
  67. * <p>Two Objects that compare equal using <code>equals(Object)</code> should normally
  68. * also compare equal using <code>compareTo(Object)</code>.</p>
  69. *
  70. * <p>All relevant fields should be included in the calculation of the
  71. * comparison. Derived fields may be ignored. The same fields, in the same
  72. * order, should be used in both <code>compareTo(Object)</code> and
  73. * <code>equals(Object)</code>.</p>
  74. *
  75. * <p>To use this class write code as follows:</p>
  76. *
  77. * <pre>
  78. * public class MyClass {
  79. * String field1;
  80. * int field2;
  81. * boolean field3;
  82. *
  83. * ...
  84. *
  85. * public int compareTo(Object o) {
  86. * MyClass myClass = (MyClass) o;
  87. * return new CompareToBuilder()
  88. * .appendSuper(super.compareTo(o)
  89. * .append(this.field1, myClass.field1)
  90. * .append(this.field2, myClass.field2)
  91. * .append(this.field3, myClass.field3)
  92. * .toComparison();
  93. * }
  94. * }
  95. * </pre>
  96. *
  97. * <p>Alternatively, there is a method {@link #reflectionCompare reflectionCompare} that uses
  98. * reflection to determine the fields to append. Because fields can be private,
  99. * <code>reflectionCompare</code> uses {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} to
  100. * bypass normal access control checks. This will fail under a security manager,
  101. * unless the appropriate permissions are set up correctly. It is also
  102. * slower than appending explicitly.</p>
  103. *
  104. * <p>A typical implementation of <code>compareTo(Object)</code> using
  105. * <code>reflectionCompare</code> looks like:</p>
  106. * <pre>
  107. * public int compareTo(Object o) {
  108. * return CompareToBuilder.reflectionCompare(this, o);
  109. * }
  110. * </pre>
  111. *
  112. * @see java.lang.Comparable
  113. * @see java.lang.Object#equals(Object)
  114. * @see java.lang.Object#hashCode()
  115. * @see EqualsBuilder
  116. * @see HashCodeBuilder
  117. * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
  118. * @author Stephen Colebourne
  119. * @author Gary Gregory
  120. * @author Pete Gieser
  121. * @since 1.0
  122. * @version $Id: CompareToBuilder.java,v 1.23 2003/08/23 00:21:49 ggregory Exp $
  123. */
  124. public class CompareToBuilder {
  125. /**
  126. * Current state of the comparison as appended fields are checked.
  127. */
  128. private int comparison;
  129. /**
  130. * <p>Constructor for CompareToBuilder.</p>
  131. *
  132. * <p>Starts off assuming that the objects are equal. Multiple calls are
  133. * then made to the various append methods, followed by a call to
  134. * {@link #toComparison} to get the result.</p>
  135. */
  136. public CompareToBuilder() {
  137. super();
  138. comparison = 0;
  139. }
  140. //-----------------------------------------------------------------------
  141. /**
  142. * <p>Compares two <code>Object</code>s via reflection.</p>
  143. *
  144. * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
  145. * is used to bypass normal access control checks. This will fail under a
  146. * security manager unless the appropriate permissions are set.</p>
  147. *
  148. * <ul>
  149. * <li>Static fields will not be compared</li>
  150. * <li>Transient members will be not be compared, as they are likely derived
  151. * fields</li>
  152. * <li>Superclass fields will be compared</li>
  153. * </ul>
  154. *
  155. * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
  156. * they are considered equal.</p>
  157. *
  158. * @param lhs left-hand object
  159. * @param rhs right-hand object
  160. * @return a negative integer, zero, or a positive integer as <code>lhs</code>
  161. * is less than, equal to, or greater than <code>rhs</code>
  162. * @throws NullPointerException if either (but not both) parameters are
  163. * <code>null</code>
  164. * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
  165. * with <code>lhs</code>
  166. */
  167. public static int reflectionCompare(Object lhs, Object rhs) {
  168. return reflectionCompare(lhs, rhs, false, null);
  169. }
  170. /**
  171. * <p>Compares two <code>Object</code>s via reflection.</p>
  172. *
  173. * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
  174. * is used to bypass normal access control checks. This will fail under a
  175. * security manager unless the appropriate permissions are set.</p>
  176. *
  177. * <ul>
  178. * <li>Static fields will not be compared</li>
  179. * <li>If <code>compareTransients</code> is <code>true</code>,
  180. * compares transient members. Otherwise ignores them, as they
  181. * are likely derived fields.</li>
  182. * <li>Superclass fields will be compared</li>
  183. * </ul>
  184. *
  185. * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
  186. * they are considered equal.</p>
  187. *
  188. * @param lhs left-hand object
  189. * @param rhs right-hand object
  190. * @param compareTransients whether to compare transient fields
  191. * @return a negative integer, zero, or a positive integer as <code>lhs</code>
  192. * is less than, equal to, or greater than <code>rhs</code>
  193. * @throws NullPointerException if either <code>lhs</code> or <code>rhs</code>
  194. * (but not both) is <code>null</code>
  195. * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
  196. * with <code>lhs</code>
  197. */
  198. public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients) {
  199. return reflectionCompare(lhs, rhs, compareTransients, null);
  200. }
  201. /**
  202. * <p>Compares two <code>Object</code>s via reflection.</p>
  203. *
  204. * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
  205. * is used to bypass normal access control checks. This will fail under a
  206. * security manager unless the appropriate permissions are set.</p>
  207. *
  208. * <ul>
  209. * <li>Static fields will not be compared</li>
  210. * <li>If the <code>compareTransients</code> is <code>true</code>,
  211. * compares transient members. Otherwise ignores them, as they
  212. * are likely derived fields.</li>
  213. * <li>Compares superclass fields up to and including <code>reflectUpToClass</code>.
  214. * If <code>reflectUpToClass</code> is <code>null</code>, compares all superclass fields.</li>
  215. * </ul>
  216. *
  217. * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
  218. * they are considered equal.</p>
  219. *
  220. * @param lhs left-hand object
  221. * @param rhs right-hand object
  222. * @param compareTransients whether to compare transient fields
  223. * @param reflectUpToClass last superclass for which fields are compared
  224. * @return a negative integer, zero, or a positive integer as <code>lhs</code>
  225. * is less than, equal to, or greater than <code>rhs</code>
  226. * @throws NullPointerException if either <code>lhs</code> or <code>rhs</code>
  227. * (but not both) is <code>null</code>
  228. * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
  229. * with <code>lhs</code>
  230. * @since 2.0
  231. */
  232. public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients, Class reflectUpToClass) {
  233. if (lhs == rhs) {
  234. return 0;
  235. }
  236. if (lhs == null || rhs == null) {
  237. throw new NullPointerException();
  238. }
  239. Class lhsClazz = lhs.getClass();
  240. if (!lhsClazz.isInstance(rhs)) {
  241. throw new ClassCastException();
  242. }
  243. CompareToBuilder compareToBuilder = new CompareToBuilder();
  244. reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients);
  245. while (lhsClazz.getSuperclass() != null && lhsClazz != reflectUpToClass) {
  246. lhsClazz = lhsClazz.getSuperclass();
  247. reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients);
  248. }
  249. return compareToBuilder.toComparison();
  250. }
  251. /**
  252. * <p>Appends to <code>builder</code> the comparison of <code>lhs</code>
  253. * to <code>rhs</code> using the fields defined in <code>clazz</code>.</p>
  254. *
  255. * @param lhs left-hand object
  256. * @param rhs right-hand object
  257. * @param clazz <code>Class</code> that defines fields to be compared
  258. * @param builder <code>CompareToBuilder</code> to append to
  259. * @param useTransients whether to compare transient fields
  260. */
  261. private static void reflectionAppend(
  262. Object lhs,
  263. Object rhs,
  264. Class clazz,
  265. CompareToBuilder builder,
  266. boolean useTransients) {
  267. Field[] fields = clazz.getDeclaredFields();
  268. AccessibleObject.setAccessible(fields, true);
  269. for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
  270. Field f = fields[i];
  271. if ((f.getName().indexOf('$') == -1)
  272. && (useTransients || !Modifier.isTransient(f.getModifiers()))
  273. && (!Modifier.isStatic(f.getModifiers()))) {
  274. try {
  275. builder.append(f.get(lhs), f.get(rhs));
  276. } catch (IllegalAccessException e) {
  277. // This can't happen. Would get a Security exception instead.
  278. // Throw a runtime exception in case the impossible happens.
  279. throw new InternalError("Unexpected IllegalAccessException");
  280. }
  281. }
  282. }
  283. }
  284. //-----------------------------------------------------------------------
  285. /**
  286. * <p>Appends to the <code>builder</code> the <code>compareTo(Object)</code>
  287. * result of the superclass.</p>
  288. *
  289. * @param superCompareTo result of calling <code>super.compareTo(Object)</code>
  290. * @return this - used to chain append calls
  291. * @since 2.0
  292. */
  293. public CompareToBuilder appendSuper(int superCompareTo) {
  294. if (comparison != 0) {
  295. return this;
  296. }
  297. comparison = superCompareTo;
  298. return this;
  299. }
  300. //-----------------------------------------------------------------------
  301. /**
  302. * <p>Appends to the <code>builder</code> the comparison of
  303. * two <code>Object</code>s.</p>
  304. *
  305. * <ol>
  306. * <li>Check if <code>lhs == rhs</code></li>
  307. * <li>Check if either <code>lhs</code> or <code>rhs</code> is <code>null</code>,
  308. * a <code>null</code> object is less than a non-<code>null</code> object</li>
  309. * <li>Check the object contents</li>
  310. * </ol>
  311. *
  312. * <p><code>lhs</code> must either be an array or implement {@link Comparable}.</p>
  313. *
  314. * @param lhs left-hand object
  315. * @param rhs right-hand object
  316. * @return this - used to chain append calls
  317. * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
  318. * with <code>lhs</code>
  319. */
  320. public CompareToBuilder append(Object lhs, Object rhs) {
  321. return append(lhs, rhs, null);
  322. }
  323. /**
  324. * <p>Appends to the <code>builder</code> the comparison of
  325. * two <code>Object</code>s.</p>
  326. *
  327. * <ol>
  328. * <li>Check if <code>lhs == rhs</code></li>
  329. * <li>Check if either <code>lhs</code> or <code>rhs</code> is <code>null</code>,
  330. * a <code>null</code> object is less than a non-<code>null</code> object</li>
  331. * <li>Check the object contents</li>
  332. * </ol>
  333. *
  334. * <p>If <code>lhs</code> is an array, array comparison methods will be used.
  335. * Otherwise <code>comparator</code> will be used to compare the objects.
  336. * If <code>comparator</code> is <code>null</code>, <code>lhs</code> must
  337. * implement {@link Comparable} instead.</p>
  338. *
  339. * @param lhs left-hand object
  340. * @param rhs right-hand object
  341. * @param comparator <code>Comparator</code> used to compare the objects,
  342. * <code>null</code> means treat lhs as <code>Comparable</code>
  343. * @return this - used to chain append calls
  344. * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
  345. * with <code>lhs</code>
  346. * @since 2.0
  347. */
  348. public CompareToBuilder append(Object lhs, Object rhs, Comparator comparator) {
  349. if (comparison != 0) {
  350. return this;
  351. }
  352. if (lhs == rhs) {
  353. return this;
  354. }
  355. if (lhs == null) {
  356. comparison = -1;
  357. return this;
  358. }
  359. if (rhs == null) {
  360. comparison = +1;
  361. return this;
  362. }
  363. if (lhs.getClass().isArray()) {
  364. // switch on type of array, to dispatch to the correct handler
  365. // handles multi dimensional arrays
  366. // throws a ClassCastException if rhs is not the correct array type
  367. if (lhs instanceof long[]) {
  368. append((long[]) lhs, (long[]) rhs);
  369. } else if (lhs instanceof int[]) {
  370. append((int[]) lhs, (int[]) rhs);
  371. } else if (lhs instanceof short[]) {
  372. append((short[]) lhs, (short[]) rhs);
  373. } else if (lhs instanceof char[]) {
  374. append((char[]) lhs, (char[]) rhs);
  375. } else if (lhs instanceof byte[]) {
  376. append((byte[]) lhs, (byte[]) rhs);
  377. } else if (lhs instanceof double[]) {
  378. append((double[]) lhs, (double[]) rhs);
  379. } else if (lhs instanceof float[]) {
  380. append((float[]) lhs, (float[]) rhs);
  381. } else if (lhs instanceof boolean[]) {
  382. append((boolean[]) lhs, (boolean[]) rhs);
  383. } else {
  384. // not an array of primitives
  385. // throws a ClassCastException if rhs is not an array
  386. append((Object[]) lhs, (Object[]) rhs, comparator);
  387. }
  388. } else {
  389. // the simple case, not an array, just test the element
  390. if (comparator == null) {
  391. comparison = ((Comparable) lhs).compareTo(rhs);
  392. } else {
  393. comparison = comparator.compare(lhs, rhs);
  394. }
  395. }
  396. return this;
  397. }
  398. //-------------------------------------------------------------------------
  399. /**
  400. * Appends to the <code>builder</code> the comparison of
  401. * two <code>long</code>s.
  402. *
  403. * @param lhs left-hand value
  404. * @param rhs right-hand value
  405. * @return this - used to chain append calls
  406. */
  407. public CompareToBuilder append(long lhs, long rhs) {
  408. if (comparison != 0) {
  409. return this;
  410. }
  411. comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
  412. return this;
  413. }
  414. /**
  415. * Appends to the <code>builder</code> the comparison of
  416. * two <code>int</code>s.
  417. *
  418. * @param lhs left-hand value
  419. * @param rhs right-hand value
  420. * @return this - used to chain append calls
  421. */
  422. public CompareToBuilder append(int lhs, int rhs) {
  423. if (comparison != 0) {
  424. return this;
  425. }
  426. comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
  427. return this;
  428. }
  429. /**
  430. * Appends to the <code>builder</code> the comparison of
  431. * two <code>short</code>s.
  432. *
  433. * @param lhs left-hand value
  434. * @param rhs right-hand value
  435. * @return this - used to chain append calls
  436. */
  437. public CompareToBuilder append(short lhs, short rhs) {
  438. if (comparison != 0) {
  439. return this;
  440. }
  441. comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
  442. return this;
  443. }
  444. /**
  445. * Appends to the <code>builder</code> the comparison of
  446. * two <code>char</code>s.
  447. *
  448. * @param lhs left-hand value
  449. * @param rhs right-hand value
  450. * @return this - used to chain append calls
  451. */
  452. public CompareToBuilder append(char lhs, char rhs) {
  453. if (comparison != 0) {
  454. return this;
  455. }
  456. comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
  457. return this;
  458. }
  459. /**
  460. * Appends to the <code>builder</code> the comparison of
  461. * two <code>byte</code>s.
  462. *
  463. * @param lhs left-hand value
  464. * @param rhs right-hand value
  465. * @return this - used to chain append calls
  466. */
  467. public CompareToBuilder append(byte lhs, byte rhs) {
  468. if (comparison != 0) {
  469. return this;
  470. }
  471. comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
  472. return this;
  473. }
  474. /**
  475. * <p>Appends to the <code>builder</code> the comparison of
  476. * two <code>double</code>s.</p>
  477. *
  478. * <p>This handles NaNs, Infinties, and <code>-0.0</code>.</p>
  479. *
  480. * <p>It is compatible with the hash code generated by
  481. * <code>HashCodeBuilder</code>.</p>
  482. *
  483. * @param lhs left-hand value
  484. * @param rhs right-hand value
  485. * @return this - used to chain append calls
  486. */
  487. public CompareToBuilder append(double lhs, double rhs) {
  488. if (comparison != 0) {
  489. return this;
  490. }
  491. comparison = NumberUtils.compare(lhs, rhs);
  492. return this;
  493. }
  494. /**
  495. * <p>Appends to the <code>builder</code> the comparison of
  496. * two <code>float</code>s.</p>
  497. *
  498. * <p>This handles NaNs, Infinties, and <code>-0.0</code>.</p>
  499. *
  500. * <p>It is compatible with the hash code generated by
  501. * <code>HashCodeBuilder</code>.</p>
  502. *
  503. * @param lhs left-hand value
  504. * @param rhs right-hand value
  505. * @return this - used to chain append calls
  506. */
  507. public CompareToBuilder append(float lhs, float rhs) {
  508. if (comparison != 0) {
  509. return this;
  510. }
  511. comparison = NumberUtils.compare(lhs, rhs);
  512. return this;
  513. }
  514. /**
  515. * Appends to the <code>builder</code> the comparison of
  516. * two <code>booleans</code>s.
  517. *
  518. * @param lhs left-hand value
  519. * @param rhs right-hand value
  520. * @return this - used to chain append calls
  521. */
  522. public CompareToBuilder append(boolean lhs, boolean rhs) {
  523. if (comparison != 0) {
  524. return this;
  525. }
  526. if (lhs == rhs) {
  527. return this;
  528. }
  529. if (lhs == false) {
  530. comparison = -1;
  531. } else {
  532. comparison = +1;
  533. }
  534. return this;
  535. }
  536. //-----------------------------------------------------------------------
  537. /**
  538. * <p>Appends to the <code>builder</code> the deep comparison of
  539. * two <code>Object</code> arrays.</p>
  540. *
  541. * <ol>
  542. * <li>Check if arrays are the same using <code>==</code></li>
  543. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  544. * <li>Check array length, a short length array is less than a long length array</li>
  545. * <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li>
  546. * </ol>
  547. *
  548. * <p>This method will also will be called for the top level of multi-dimensional,
  549. * ragged, and multi-typed arrays.</p>
  550. *
  551. * @param lhs left-hand array
  552. * @param rhs right-hand array
  553. * @return this - used to chain append calls
  554. * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
  555. * with <code>lhs</code>
  556. */
  557. public CompareToBuilder append(Object[] lhs, Object[] rhs) {
  558. return append(lhs, rhs, null);
  559. }
  560. /**
  561. * <p>Appends to the <code>builder</code> the deep comparison of
  562. * two <code>Object</code> arrays.</p>
  563. *
  564. * <ol>
  565. * <li>Check if arrays are the same using <code>==</code></li>
  566. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  567. * <li>Check array length, a short length array is less than a long length array</li>
  568. * <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li>
  569. * </ol>
  570. *
  571. * <p>This method will also will be called for the top level of multi-dimensional,
  572. * ragged, and multi-typed arrays.</p>
  573. *
  574. * @param lhs left-hand array
  575. * @param rhs right-hand array
  576. * @param comparator <code>Comparator</code> to use to compare the array elements,
  577. * <code>null</code> means to treat <code>lhs</code> elements as <code>Comparable</code>.
  578. * @return this - used to chain append calls
  579. * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
  580. * with <code>lhs</code>
  581. * @since 2.0
  582. */
  583. public CompareToBuilder append(Object[] lhs, Object[] rhs, Comparator comparator) {
  584. if (comparison != 0) {
  585. return this;
  586. }
  587. if (lhs == rhs) {
  588. return this;
  589. }
  590. if (lhs == null) {
  591. comparison = -1;
  592. return this;
  593. }
  594. if (rhs == null) {
  595. comparison = +1;
  596. return this;
  597. }
  598. if (lhs.length != rhs.length) {
  599. comparison = (lhs.length < rhs.length) ? -1 : +1;
  600. return this;
  601. }
  602. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  603. append(lhs[i], rhs[i], comparator);
  604. }
  605. return this;
  606. }
  607. /**
  608. * <p>Appends to the <code>builder</code> the deep comparison of
  609. * two <code>long</code> arrays.</p>
  610. *
  611. * <ol>
  612. * <li>Check if arrays are the same using <code>==</code></li>
  613. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  614. * <li>Check array length, a shorter length array is less than a longer length array</li>
  615. * <li>Check array contents element by element using {@link #append(long, long)}</li>
  616. * </ol>
  617. *
  618. * @param lhs left-hand array
  619. * @param rhs right-hand array
  620. * @return this - used to chain append calls
  621. */
  622. public CompareToBuilder append(long[] lhs, long[] rhs) {
  623. if (comparison != 0) {
  624. return this;
  625. }
  626. if (lhs == rhs) {
  627. return this;
  628. }
  629. if (lhs == null) {
  630. comparison = -1;
  631. return this;
  632. }
  633. if (rhs == null) {
  634. comparison = +1;
  635. return this;
  636. }
  637. if (lhs.length != rhs.length) {
  638. comparison = (lhs.length < rhs.length) ? -1 : +1;
  639. return this;
  640. }
  641. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  642. append(lhs[i], rhs[i]);
  643. }
  644. return this;
  645. }
  646. /**
  647. * <p>Appends to the <code>builder</code> the deep comparison of
  648. * two <code>int</code> arrays.</p>
  649. *
  650. * <ol>
  651. * <li>Check if arrays are the same using <code>==</code></li>
  652. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  653. * <li>Check array length, a shorter length array is less than a longer length array</li>
  654. * <li>Check array contents element by element using {@link #append(int, int)}</li>
  655. * </ol>
  656. *
  657. * @param lhs left-hand array
  658. * @param rhs right-hand array
  659. * @return this - used to chain append calls
  660. */
  661. public CompareToBuilder append(int[] lhs, int[] rhs) {
  662. if (comparison != 0) {
  663. return this;
  664. }
  665. if (lhs == rhs) {
  666. return this;
  667. }
  668. if (lhs == null) {
  669. comparison = -1;
  670. return this;
  671. }
  672. if (rhs == null) {
  673. comparison = +1;
  674. return this;
  675. }
  676. if (lhs.length != rhs.length) {
  677. comparison = (lhs.length < rhs.length) ? -1 : +1;
  678. return this;
  679. }
  680. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  681. append(lhs[i], rhs[i]);
  682. }
  683. return this;
  684. }
  685. /**
  686. * <p>Appends to the <code>builder</code> the deep comparison of
  687. * two <code>short</code> arrays.</p>
  688. *
  689. * <ol>
  690. * <li>Check if arrays are the same using <code>==</code></li>
  691. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  692. * <li>Check array length, a shorter length array is less than a longer length array</li>
  693. * <li>Check array contents element by element using {@link #append(short, short)}</li>
  694. * </ol>
  695. *
  696. * @param lhs left-hand array
  697. * @param rhs right-hand array
  698. * @return this - used to chain append calls
  699. */
  700. public CompareToBuilder append(short[] lhs, short[] rhs) {
  701. if (comparison != 0) {
  702. return this;
  703. }
  704. if (lhs == rhs) {
  705. return this;
  706. }
  707. if (lhs == null) {
  708. comparison = -1;
  709. return this;
  710. }
  711. if (rhs == null) {
  712. comparison = +1;
  713. return this;
  714. }
  715. if (lhs.length != rhs.length) {
  716. comparison = (lhs.length < rhs.length) ? -1 : +1;
  717. return this;
  718. }
  719. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  720. append(lhs[i], rhs[i]);
  721. }
  722. return this;
  723. }
  724. /**
  725. * <p>Appends to the <code>builder</code> the deep comparison of
  726. * two <code>char</code> arrays.</p>
  727. *
  728. * <ol>
  729. * <li>Check if arrays are the same using <code>==</code></li>
  730. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  731. * <li>Check array length, a shorter length array is less than a longer length array</li>
  732. * <li>Check array contents element by element using {@link #append(char, char)}</li>
  733. * </ol>
  734. *
  735. * @param lhs left-hand array
  736. * @param rhs right-hand array
  737. * @return this - used to chain append calls
  738. */
  739. public CompareToBuilder append(char[] lhs, char[] rhs) {
  740. if (comparison != 0) {
  741. return this;
  742. }
  743. if (lhs == rhs) {
  744. return this;
  745. }
  746. if (lhs == null) {
  747. comparison = -1;
  748. return this;
  749. }
  750. if (rhs == null) {
  751. comparison = +1;
  752. return this;
  753. }
  754. if (lhs.length != rhs.length) {
  755. comparison = (lhs.length < rhs.length) ? -1 : +1;
  756. return this;
  757. }
  758. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  759. append(lhs[i], rhs[i]);
  760. }
  761. return this;
  762. }
  763. /**
  764. * <p>Appends to the <code>builder</code> the deep comparison of
  765. * two <code>byte</code> arrays.</p>
  766. *
  767. * <ol>
  768. * <li>Check if arrays are the same using <code>==</code></li>
  769. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  770. * <li>Check array length, a shorter length array is less than a longer length array</li>
  771. * <li>Check array contents element by element using {@link #append(byte, byte)}</li>
  772. * </ol>
  773. *
  774. * @param lhs left-hand array
  775. * @param rhs right-hand array
  776. * @return this - used to chain append calls
  777. */
  778. public CompareToBuilder append(byte[] lhs, byte[] rhs) {
  779. if (comparison != 0) {
  780. return this;
  781. }
  782. if (lhs == rhs) {
  783. return this;
  784. }
  785. if (lhs == null) {
  786. comparison = -1;
  787. return this;
  788. }
  789. if (rhs == null) {
  790. comparison = +1;
  791. return this;
  792. }
  793. if (lhs.length != rhs.length) {
  794. comparison = (lhs.length < rhs.length) ? -1 : +1;
  795. return this;
  796. }
  797. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  798. append(lhs[i], rhs[i]);
  799. }
  800. return this;
  801. }
  802. /**
  803. * <p>Appends to the <code>builder</code> the deep comparison of
  804. * two <code>double</code> arrays.</p>
  805. *
  806. * <ol>
  807. * <li>Check if arrays are the same using <code>==</code></li>
  808. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  809. * <li>Check array length, a shorter length array is less than a longer length array</li>
  810. * <li>Check array contents element by element using {@link #append(double, double)}</li>
  811. * </ol>
  812. *
  813. * @param lhs left-hand array
  814. * @param rhs right-hand array
  815. * @return this - used to chain append calls
  816. */
  817. public CompareToBuilder append(double[] lhs, double[] rhs) {
  818. if (comparison != 0) {
  819. return this;
  820. }
  821. if (lhs == rhs) {
  822. return this;
  823. }
  824. if (lhs == null) {
  825. comparison = -1;
  826. return this;
  827. }
  828. if (rhs == null) {
  829. comparison = +1;
  830. return this;
  831. }
  832. if (lhs.length != rhs.length) {
  833. comparison = (lhs.length < rhs.length) ? -1 : +1;
  834. return this;
  835. }
  836. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  837. append(lhs[i], rhs[i]);
  838. }
  839. return this;
  840. }
  841. /**
  842. * <p>Appends to the <code>builder</code> the deep comparison of
  843. * two <code>float</code> arrays.</p>
  844. *
  845. * <ol>
  846. * <li>Check if arrays are the same using <code>==</code></li>
  847. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  848. * <li>Check array length, a shorter length array is less than a longer length array</li>
  849. * <li>Check array contents element by element using {@link #append(float, float)}</li>
  850. * </ol>
  851. *
  852. * @param lhs left-hand array
  853. * @param rhs right-hand array
  854. * @return this - used to chain append calls
  855. */
  856. public CompareToBuilder append(float[] lhs, float[] rhs) {
  857. if (comparison != 0) {
  858. return this;
  859. }
  860. if (lhs == rhs) {
  861. return this;
  862. }
  863. if (lhs == null) {
  864. comparison = -1;
  865. return this;
  866. }
  867. if (rhs == null) {
  868. comparison = +1;
  869. return this;
  870. }
  871. if (lhs.length != rhs.length) {
  872. comparison = (lhs.length < rhs.length) ? -1 : +1;
  873. return this;
  874. }
  875. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  876. append(lhs[i], rhs[i]);
  877. }
  878. return this;
  879. }
  880. /**
  881. * <p>Appends to the <code>builder</code> the deep comparison of
  882. * two <code>boolean</code> arrays.</p>
  883. *
  884. * <ol>
  885. * <li>Check if arrays are the same using <code>==</code></li>
  886. * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
  887. * <li>Check array length, a shorter length array is less than a longer length array</li>
  888. * <li>Check array contents element by element using {@link #append(boolean, boolean)}</li>
  889. * </ol>
  890. *
  891. * @param lhs left-hand array
  892. * @param rhs right-hand array
  893. * @return this - used to chain append calls
  894. */
  895. public CompareToBuilder append(boolean[] lhs, boolean[] rhs) {
  896. if (comparison != 0) {
  897. return this;
  898. }
  899. if (lhs == rhs) {
  900. return this;
  901. }
  902. if (lhs == null) {
  903. comparison = -1;
  904. return this;
  905. }
  906. if (rhs == null) {
  907. comparison = +1;
  908. return this;
  909. }
  910. if (lhs.length != rhs.length) {
  911. comparison = (lhs.length < rhs.length) ? -1 : +1;
  912. return this;
  913. }
  914. for (int i = 0; i < lhs.length && comparison == 0; i++) {
  915. append(lhs[i], rhs[i]);
  916. }
  917. return this;
  918. }
  919. //-----------------------------------------------------------------------
  920. /**
  921. * Returns a negative integer, a positive integer, or zero as
  922. * the <code>builder</code> has judged the "left-hand" side
  923. * as less than, greater than, or equal to the "right-hand"
  924. * side.
  925. *
  926. * @return final comparison result
  927. */
  928. public int toComparison() {
  929. return comparison;
  930. }
  931. }