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