001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.lang3.builder;
018
019 import java.lang.reflect.AccessibleObject;
020 import java.lang.reflect.Field;
021 import java.lang.reflect.Modifier;
022 import java.util.Collection;
023 import java.util.Comparator;
024
025 import org.apache.commons.lang3.ArrayUtils;
026
027 /**
028 * Assists in implementing {@link java.lang.Comparable#compareTo(Object)} methods.
029 *
030 * It is consistent with <code>equals(Object)</code> and
031 * <code>hashcode()</code> built with {@link EqualsBuilder} and
032 * {@link HashCodeBuilder}.</p>
033 *
034 * <p>Two Objects that compare equal using <code>equals(Object)</code> should normally
035 * also compare equal using <code>compareTo(Object)</code>.</p>
036 *
037 * <p>All relevant fields should be included in the calculation of the
038 * comparison. Derived fields may be ignored. The same fields, in the same
039 * order, should be used in both <code>compareTo(Object)</code> and
040 * <code>equals(Object)</code>.</p>
041 *
042 * <p>To use this class write code as follows:</p>
043 *
044 * <pre>
045 * public class MyClass {
046 * String field1;
047 * int field2;
048 * boolean field3;
049 *
050 * ...
051 *
052 * public int compareTo(Object o) {
053 * MyClass myClass = (MyClass) o;
054 * return new CompareToBuilder()
055 * .appendSuper(super.compareTo(o)
056 * .append(this.field1, myClass.field1)
057 * .append(this.field2, myClass.field2)
058 * .append(this.field3, myClass.field3)
059 * .toComparison();
060 * }
061 * }
062 * </pre>
063 *
064 * <p>Alternatively, there are {@link #reflectionCompare(Object, Object) reflectionCompare} methods that use
065 * reflection to determine the fields to append. Because fields can be private,
066 * <code>reflectionCompare</code> uses {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} to
067 * bypass normal access control checks. This will fail under a security manager,
068 * unless the appropriate permissions are set up correctly. It is also
069 * slower than appending explicitly.</p>
070 *
071 * <p>A typical implementation of <code>compareTo(Object)</code> using
072 * <code>reflectionCompare</code> looks like:</p>
073
074 * <pre>
075 * public int compareTo(Object o) {
076 * return CompareToBuilder.reflectionCompare(this, o);
077 * }
078 * </pre>
079 *
080 * @see java.lang.Comparable
081 * @see java.lang.Object#equals(Object)
082 * @see java.lang.Object#hashCode()
083 * @see EqualsBuilder
084 * @see HashCodeBuilder
085 * @since 1.0
086 * @version $Id: CompareToBuilder.java 1199735 2011-11-09 13:11:07Z sebb $
087 */
088 public class CompareToBuilder implements Builder<Integer> {
089
090 /**
091 * Current state of the comparison as appended fields are checked.
092 */
093 private int comparison;
094
095 /**
096 * <p>Constructor for CompareToBuilder.</p>
097 *
098 * <p>Starts off assuming that the objects are equal. Multiple calls are
099 * then made to the various append methods, followed by a call to
100 * {@link #toComparison} to get the result.</p>
101 */
102 public CompareToBuilder() {
103 super();
104 comparison = 0;
105 }
106
107 //-----------------------------------------------------------------------
108 /**
109 * <p>Compares two <code>Object</code>s via reflection.</p>
110 *
111 * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
112 * is used to bypass normal access control checks. This will fail under a
113 * security manager unless the appropriate permissions are set.</p>
114 *
115 * <ul>
116 * <li>Static fields will not be compared</li>
117 * <li>Transient members will be not be compared, as they are likely derived
118 * fields</li>
119 * <li>Superclass fields will be compared</li>
120 * </ul>
121 *
122 * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
123 * they are considered equal.</p>
124 *
125 * @param lhs left-hand object
126 * @param rhs right-hand object
127 * @return a negative integer, zero, or a positive integer as <code>lhs</code>
128 * is less than, equal to, or greater than <code>rhs</code>
129 * @throws NullPointerException if either (but not both) parameters are
130 * <code>null</code>
131 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
132 * with <code>lhs</code>
133 */
134 public static int reflectionCompare(Object lhs, Object rhs) {
135 return reflectionCompare(lhs, rhs, false, null);
136 }
137
138 /**
139 * <p>Compares two <code>Object</code>s via reflection.</p>
140 *
141 * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
142 * is used to bypass normal access control checks. This will fail under a
143 * security manager unless the appropriate permissions are set.</p>
144 *
145 * <ul>
146 * <li>Static fields will not be compared</li>
147 * <li>If <code>compareTransients</code> is <code>true</code>,
148 * compares transient members. Otherwise ignores them, as they
149 * are likely derived fields.</li>
150 * <li>Superclass fields will be compared</li>
151 * </ul>
152 *
153 * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
154 * they are considered equal.</p>
155 *
156 * @param lhs left-hand object
157 * @param rhs right-hand object
158 * @param compareTransients whether to compare transient fields
159 * @return a negative integer, zero, or a positive integer as <code>lhs</code>
160 * is less than, equal to, or greater than <code>rhs</code>
161 * @throws NullPointerException if either <code>lhs</code> or <code>rhs</code>
162 * (but not both) is <code>null</code>
163 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
164 * with <code>lhs</code>
165 */
166 public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients) {
167 return reflectionCompare(lhs, rhs, compareTransients, null);
168 }
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 excludeFields Collection of String fields to exclude
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 * @since 2.2
198 */
199 public static int reflectionCompare(Object lhs, Object rhs, Collection<String> excludeFields) {
200 return reflectionCompare(lhs, rhs, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
201 }
202
203 /**
204 * <p>Compares two <code>Object</code>s via reflection.</p>
205 *
206 * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
207 * is used to bypass normal access control checks. This will fail under a
208 * security manager unless the appropriate permissions are set.</p>
209 *
210 * <ul>
211 * <li>Static fields will not be compared</li>
212 * <li>If <code>compareTransients</code> is <code>true</code>,
213 * compares transient members. Otherwise ignores them, as they
214 * are likely derived fields.</li>
215 * <li>Superclass fields will be compared</li>
216 * </ul>
217 *
218 * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
219 * they are considered equal.</p>
220 *
221 * @param lhs left-hand object
222 * @param rhs right-hand object
223 * @param excludeFields array of fields to exclude
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.2
231 */
232 public static int reflectionCompare(Object lhs, Object rhs, String... excludeFields) {
233 return reflectionCompare(lhs, rhs, false, null, excludeFields);
234 }
235
236 /**
237 * <p>Compares two <code>Object</code>s via reflection.</p>
238 *
239 * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
240 * is used to bypass normal access control checks. This will fail under a
241 * security manager unless the appropriate permissions are set.</p>
242 *
243 * <ul>
244 * <li>Static fields will not be compared</li>
245 * <li>If the <code>compareTransients</code> is <code>true</code>,
246 * compares transient members. Otherwise ignores them, as they
247 * are likely derived fields.</li>
248 * <li>Compares superclass fields up to and including <code>reflectUpToClass</code>.
249 * If <code>reflectUpToClass</code> is <code>null</code>, compares all superclass fields.</li>
250 * </ul>
251 *
252 * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
253 * they are considered equal.</p>
254 *
255 * @param lhs left-hand object
256 * @param rhs right-hand object
257 * @param compareTransients whether to compare transient fields
258 * @param reflectUpToClass last superclass for which fields are compared
259 * @param excludeFields fields to exclude
260 * @return a negative integer, zero, or a positive integer as <code>lhs</code>
261 * is less than, equal to, or greater than <code>rhs</code>
262 * @throws NullPointerException if either <code>lhs</code> or <code>rhs</code>
263 * (but not both) is <code>null</code>
264 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
265 * with <code>lhs</code>
266 * @since 2.2 (2.0 as <code>reflectionCompare(Object, Object, boolean, Class)</code>)
267 */
268 public static int reflectionCompare(
269 Object lhs,
270 Object rhs,
271 boolean compareTransients,
272 Class<?> reflectUpToClass,
273 String... excludeFields) {
274
275 if (lhs == rhs) {
276 return 0;
277 }
278 if (lhs == null || rhs == null) {
279 throw new NullPointerException();
280 }
281 Class<?> lhsClazz = lhs.getClass();
282 if (!lhsClazz.isInstance(rhs)) {
283 throw new ClassCastException();
284 }
285 CompareToBuilder compareToBuilder = new CompareToBuilder();
286 reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields);
287 while (lhsClazz.getSuperclass() != null && lhsClazz != reflectUpToClass) {
288 lhsClazz = lhsClazz.getSuperclass();
289 reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields);
290 }
291 return compareToBuilder.toComparison();
292 }
293
294 /**
295 * <p>Appends to <code>builder</code> the comparison of <code>lhs</code>
296 * to <code>rhs</code> using the fields defined in <code>clazz</code>.</p>
297 *
298 * @param lhs left-hand object
299 * @param rhs right-hand object
300 * @param clazz <code>Class</code> that defines fields to be compared
301 * @param builder <code>CompareToBuilder</code> to append to
302 * @param useTransients whether to compare transient fields
303 * @param excludeFields fields to exclude
304 */
305 private static void reflectionAppend(
306 Object lhs,
307 Object rhs,
308 Class<?> clazz,
309 CompareToBuilder builder,
310 boolean useTransients,
311 String[] excludeFields) {
312
313 Field[] fields = clazz.getDeclaredFields();
314 AccessibleObject.setAccessible(fields, true);
315 for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
316 Field f = fields[i];
317 if (!ArrayUtils.contains(excludeFields, f.getName())
318 && (f.getName().indexOf('$') == -1)
319 && (useTransients || !Modifier.isTransient(f.getModifiers()))
320 && (!Modifier.isStatic(f.getModifiers()))) {
321 try {
322 builder.append(f.get(lhs), f.get(rhs));
323 } catch (IllegalAccessException e) {
324 // This can't happen. Would get a Security exception instead.
325 // Throw a runtime exception in case the impossible happens.
326 throw new InternalError("Unexpected IllegalAccessException");
327 }
328 }
329 }
330 }
331
332 //-----------------------------------------------------------------------
333 /**
334 * <p>Appends to the <code>builder</code> the <code>compareTo(Object)</code>
335 * result of the superclass.</p>
336 *
337 * @param superCompareTo result of calling <code>super.compareTo(Object)</code>
338 * @return this - used to chain append calls
339 * @since 2.0
340 */
341 public CompareToBuilder appendSuper(int superCompareTo) {
342 if (comparison != 0) {
343 return this;
344 }
345 comparison = superCompareTo;
346 return this;
347 }
348
349 //-----------------------------------------------------------------------
350 /**
351 * <p>Appends to the <code>builder</code> the comparison of
352 * two <code>Object</code>s.</p>
353 *
354 * <ol>
355 * <li>Check if <code>lhs == rhs</code></li>
356 * <li>Check if either <code>lhs</code> or <code>rhs</code> is <code>null</code>,
357 * a <code>null</code> object is less than a non-<code>null</code> object</li>
358 * <li>Check the object contents</li>
359 * </ol>
360 *
361 * <p><code>lhs</code> must either be an array or implement {@link Comparable}.</p>
362 *
363 * @param lhs left-hand object
364 * @param rhs right-hand object
365 * @return this - used to chain append calls
366 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
367 * with <code>lhs</code>
368 */
369 public CompareToBuilder append(Object lhs, Object rhs) {
370 return append(lhs, rhs, null);
371 }
372
373 /**
374 * <p>Appends to the <code>builder</code> the comparison of
375 * two <code>Object</code>s.</p>
376 *
377 * <ol>
378 * <li>Check if <code>lhs == rhs</code></li>
379 * <li>Check if either <code>lhs</code> or <code>rhs</code> is <code>null</code>,
380 * a <code>null</code> object is less than a non-<code>null</code> object</li>
381 * <li>Check the object contents</li>
382 * </ol>
383 *
384 * <p>If <code>lhs</code> is an array, array comparison methods will be used.
385 * Otherwise <code>comparator</code> will be used to compare the objects.
386 * If <code>comparator</code> is <code>null</code>, <code>lhs</code> must
387 * implement {@link Comparable} instead.</p>
388 *
389 * @param lhs left-hand object
390 * @param rhs right-hand object
391 * @param comparator <code>Comparator</code> used to compare the objects,
392 * <code>null</code> means treat lhs as <code>Comparable</code>
393 * @return this - used to chain append calls
394 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
395 * with <code>lhs</code>
396 * @since 2.0
397 */
398 public CompareToBuilder append(Object lhs, Object rhs, Comparator<?> comparator) {
399 if (comparison != 0) {
400 return this;
401 }
402 if (lhs == rhs) {
403 return this;
404 }
405 if (lhs == null) {
406 comparison = -1;
407 return this;
408 }
409 if (rhs == null) {
410 comparison = +1;
411 return this;
412 }
413 if (lhs.getClass().isArray()) {
414 // switch on type of array, to dispatch to the correct handler
415 // handles multi dimensional arrays
416 // throws a ClassCastException if rhs is not the correct array type
417 if (lhs instanceof long[]) {
418 append((long[]) lhs, (long[]) rhs);
419 } else if (lhs instanceof int[]) {
420 append((int[]) lhs, (int[]) rhs);
421 } else if (lhs instanceof short[]) {
422 append((short[]) lhs, (short[]) rhs);
423 } else if (lhs instanceof char[]) {
424 append((char[]) lhs, (char[]) rhs);
425 } else if (lhs instanceof byte[]) {
426 append((byte[]) lhs, (byte[]) rhs);
427 } else if (lhs instanceof double[]) {
428 append((double[]) lhs, (double[]) rhs);
429 } else if (lhs instanceof float[]) {
430 append((float[]) lhs, (float[]) rhs);
431 } else if (lhs instanceof boolean[]) {
432 append((boolean[]) lhs, (boolean[]) rhs);
433 } else {
434 // not an array of primitives
435 // throws a ClassCastException if rhs is not an array
436 append((Object[]) lhs, (Object[]) rhs, comparator);
437 }
438 } else {
439 // the simple case, not an array, just test the element
440 if (comparator == null) {
441 @SuppressWarnings("unchecked") // assume this can be done; if not throw CCE as per Javadoc
442 final Comparable<Object> comparable = (Comparable<Object>) lhs;
443 comparison = comparable.compareTo(rhs);
444 } else {
445 @SuppressWarnings("unchecked") // assume this can be done; if not throw CCE as per Javadoc
446 final Comparator<Object> comparator2 = (Comparator<Object>) comparator;
447 comparison = comparator2.compare(lhs, rhs);
448 }
449 }
450 return this;
451 }
452
453 //-------------------------------------------------------------------------
454 /**
455 * Appends to the <code>builder</code> the comparison of
456 * two <code>long</code>s.
457 *
458 * @param lhs left-hand value
459 * @param rhs right-hand value
460 * @return this - used to chain append calls
461 */
462 public CompareToBuilder append(long lhs, long rhs) {
463 if (comparison != 0) {
464 return this;
465 }
466 comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
467 return this;
468 }
469
470 /**
471 * Appends to the <code>builder</code> the comparison of
472 * two <code>int</code>s.
473 *
474 * @param lhs left-hand value
475 * @param rhs right-hand value
476 * @return this - used to chain append calls
477 */
478 public CompareToBuilder append(int lhs, int rhs) {
479 if (comparison != 0) {
480 return this;
481 }
482 comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
483 return this;
484 }
485
486 /**
487 * Appends to the <code>builder</code> the comparison of
488 * two <code>short</code>s.
489 *
490 * @param lhs left-hand value
491 * @param rhs right-hand value
492 * @return this - used to chain append calls
493 */
494 public CompareToBuilder append(short lhs, short rhs) {
495 if (comparison != 0) {
496 return this;
497 }
498 comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
499 return this;
500 }
501
502 /**
503 * Appends to the <code>builder</code> the comparison of
504 * two <code>char</code>s.
505 *
506 * @param lhs left-hand value
507 * @param rhs right-hand value
508 * @return this - used to chain append calls
509 */
510 public CompareToBuilder append(char lhs, char rhs) {
511 if (comparison != 0) {
512 return this;
513 }
514 comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
515 return this;
516 }
517
518 /**
519 * Appends to the <code>builder</code> the comparison of
520 * two <code>byte</code>s.
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(byte lhs, byte rhs) {
527 if (comparison != 0) {
528 return this;
529 }
530 comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
531 return this;
532 }
533
534 /**
535 * <p>Appends to the <code>builder</code> the comparison of
536 * two <code>double</code>s.</p>
537 *
538 * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
539 *
540 * <p>It is compatible with the hash code generated by
541 * <code>HashCodeBuilder</code>.</p>
542 *
543 * @param lhs left-hand value
544 * @param rhs right-hand value
545 * @return this - used to chain append calls
546 */
547 public CompareToBuilder append(double lhs, double rhs) {
548 if (comparison != 0) {
549 return this;
550 }
551 comparison = Double.compare(lhs, rhs);
552 return this;
553 }
554
555 /**
556 * <p>Appends to the <code>builder</code> the comparison of
557 * two <code>float</code>s.</p>
558 *
559 * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
560 *
561 * <p>It is compatible with the hash code generated by
562 * <code>HashCodeBuilder</code>.</p>
563 *
564 * @param lhs left-hand value
565 * @param rhs right-hand value
566 * @return this - used to chain append calls
567 */
568 public CompareToBuilder append(float lhs, float rhs) {
569 if (comparison != 0) {
570 return this;
571 }
572 comparison = Float.compare(lhs, rhs);
573 return this;
574 }
575
576 /**
577 * Appends to the <code>builder</code> the comparison of
578 * two <code>booleans</code>s.
579 *
580 * @param lhs left-hand value
581 * @param rhs right-hand value
582 * @return this - used to chain append calls
583 */
584 public CompareToBuilder append(boolean lhs, boolean rhs) {
585 if (comparison != 0) {
586 return this;
587 }
588 if (lhs == rhs) {
589 return this;
590 }
591 if (lhs == false) {
592 comparison = -1;
593 } else {
594 comparison = +1;
595 }
596 return this;
597 }
598
599 //-----------------------------------------------------------------------
600 /**
601 * <p>Appends to the <code>builder</code> the deep comparison of
602 * two <code>Object</code> arrays.</p>
603 *
604 * <ol>
605 * <li>Check if arrays are the same using <code>==</code></li>
606 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
607 * <li>Check array length, a short length array is less than a long length array</li>
608 * <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li>
609 * </ol>
610 *
611 * <p>This method will also will be called for the top level of multi-dimensional,
612 * ragged, and multi-typed arrays.</p>
613 *
614 * @param lhs left-hand array
615 * @param rhs right-hand array
616 * @return this - used to chain append calls
617 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
618 * with <code>lhs</code>
619 */
620 public CompareToBuilder append(Object[] lhs, Object[] rhs) {
621 return append(lhs, rhs, null);
622 }
623
624 /**
625 * <p>Appends to the <code>builder</code> the deep comparison of
626 * two <code>Object</code> arrays.</p>
627 *
628 * <ol>
629 * <li>Check if arrays are the same using <code>==</code></li>
630 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
631 * <li>Check array length, a short length array is less than a long length array</li>
632 * <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li>
633 * </ol>
634 *
635 * <p>This method will also will be called for the top level of multi-dimensional,
636 * ragged, and multi-typed arrays.</p>
637 *
638 * @param lhs left-hand array
639 * @param rhs right-hand array
640 * @param comparator <code>Comparator</code> to use to compare the array elements,
641 * <code>null</code> means to treat <code>lhs</code> elements as <code>Comparable</code>.
642 * @return this - used to chain append calls
643 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible
644 * with <code>lhs</code>
645 * @since 2.0
646 */
647 public CompareToBuilder append(Object[] lhs, Object[] rhs, Comparator<?> comparator) {
648 if (comparison != 0) {
649 return this;
650 }
651 if (lhs == rhs) {
652 return this;
653 }
654 if (lhs == null) {
655 comparison = -1;
656 return this;
657 }
658 if (rhs == null) {
659 comparison = +1;
660 return this;
661 }
662 if (lhs.length != rhs.length) {
663 comparison = (lhs.length < rhs.length) ? -1 : +1;
664 return this;
665 }
666 for (int i = 0; i < lhs.length && comparison == 0; i++) {
667 append(lhs[i], rhs[i], comparator);
668 }
669 return this;
670 }
671
672 /**
673 * <p>Appends to the <code>builder</code> the deep comparison of
674 * two <code>long</code> arrays.</p>
675 *
676 * <ol>
677 * <li>Check if arrays are the same using <code>==</code></li>
678 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
679 * <li>Check array length, a shorter length array is less than a longer length array</li>
680 * <li>Check array contents element by element using {@link #append(long, long)}</li>
681 * </ol>
682 *
683 * @param lhs left-hand array
684 * @param rhs right-hand array
685 * @return this - used to chain append calls
686 */
687 public CompareToBuilder append(long[] lhs, long[] rhs) {
688 if (comparison != 0) {
689 return this;
690 }
691 if (lhs == rhs) {
692 return this;
693 }
694 if (lhs == null) {
695 comparison = -1;
696 return this;
697 }
698 if (rhs == null) {
699 comparison = +1;
700 return this;
701 }
702 if (lhs.length != rhs.length) {
703 comparison = (lhs.length < rhs.length) ? -1 : +1;
704 return this;
705 }
706 for (int i = 0; i < lhs.length && comparison == 0; i++) {
707 append(lhs[i], rhs[i]);
708 }
709 return this;
710 }
711
712 /**
713 * <p>Appends to the <code>builder</code> the deep comparison of
714 * two <code>int</code> arrays.</p>
715 *
716 * <ol>
717 * <li>Check if arrays are the same using <code>==</code></li>
718 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
719 * <li>Check array length, a shorter length array is less than a longer length array</li>
720 * <li>Check array contents element by element using {@link #append(int, int)}</li>
721 * </ol>
722 *
723 * @param lhs left-hand array
724 * @param rhs right-hand array
725 * @return this - used to chain append calls
726 */
727 public CompareToBuilder append(int[] lhs, int[] rhs) {
728 if (comparison != 0) {
729 return this;
730 }
731 if (lhs == rhs) {
732 return this;
733 }
734 if (lhs == null) {
735 comparison = -1;
736 return this;
737 }
738 if (rhs == null) {
739 comparison = +1;
740 return this;
741 }
742 if (lhs.length != rhs.length) {
743 comparison = (lhs.length < rhs.length) ? -1 : +1;
744 return this;
745 }
746 for (int i = 0; i < lhs.length && comparison == 0; i++) {
747 append(lhs[i], rhs[i]);
748 }
749 return this;
750 }
751
752 /**
753 * <p>Appends to the <code>builder</code> the deep comparison of
754 * two <code>short</code> arrays.</p>
755 *
756 * <ol>
757 * <li>Check if arrays are the same using <code>==</code></li>
758 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
759 * <li>Check array length, a shorter length array is less than a longer length array</li>
760 * <li>Check array contents element by element using {@link #append(short, short)}</li>
761 * </ol>
762 *
763 * @param lhs left-hand array
764 * @param rhs right-hand array
765 * @return this - used to chain append calls
766 */
767 public CompareToBuilder append(short[] lhs, short[] rhs) {
768 if (comparison != 0) {
769 return this;
770 }
771 if (lhs == rhs) {
772 return this;
773 }
774 if (lhs == null) {
775 comparison = -1;
776 return this;
777 }
778 if (rhs == null) {
779 comparison = +1;
780 return this;
781 }
782 if (lhs.length != rhs.length) {
783 comparison = (lhs.length < rhs.length) ? -1 : +1;
784 return this;
785 }
786 for (int i = 0; i < lhs.length && comparison == 0; i++) {
787 append(lhs[i], rhs[i]);
788 }
789 return this;
790 }
791
792 /**
793 * <p>Appends to the <code>builder</code> the deep comparison of
794 * two <code>char</code> arrays.</p>
795 *
796 * <ol>
797 * <li>Check if arrays are the same using <code>==</code></li>
798 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
799 * <li>Check array length, a shorter length array is less than a longer length array</li>
800 * <li>Check array contents element by element using {@link #append(char, char)}</li>
801 * </ol>
802 *
803 * @param lhs left-hand array
804 * @param rhs right-hand array
805 * @return this - used to chain append calls
806 */
807 public CompareToBuilder append(char[] lhs, char[] rhs) {
808 if (comparison != 0) {
809 return this;
810 }
811 if (lhs == rhs) {
812 return this;
813 }
814 if (lhs == null) {
815 comparison = -1;
816 return this;
817 }
818 if (rhs == null) {
819 comparison = +1;
820 return this;
821 }
822 if (lhs.length != rhs.length) {
823 comparison = (lhs.length < rhs.length) ? -1 : +1;
824 return this;
825 }
826 for (int i = 0; i < lhs.length && comparison == 0; i++) {
827 append(lhs[i], rhs[i]);
828 }
829 return this;
830 }
831
832 /**
833 * <p>Appends to the <code>builder</code> the deep comparison of
834 * two <code>byte</code> arrays.</p>
835 *
836 * <ol>
837 * <li>Check if arrays are the same using <code>==</code></li>
838 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
839 * <li>Check array length, a shorter length array is less than a longer length array</li>
840 * <li>Check array contents element by element using {@link #append(byte, byte)}</li>
841 * </ol>
842 *
843 * @param lhs left-hand array
844 * @param rhs right-hand array
845 * @return this - used to chain append calls
846 */
847 public CompareToBuilder append(byte[] lhs, byte[] rhs) {
848 if (comparison != 0) {
849 return this;
850 }
851 if (lhs == rhs) {
852 return this;
853 }
854 if (lhs == null) {
855 comparison = -1;
856 return this;
857 }
858 if (rhs == null) {
859 comparison = +1;
860 return this;
861 }
862 if (lhs.length != rhs.length) {
863 comparison = (lhs.length < rhs.length) ? -1 : +1;
864 return this;
865 }
866 for (int i = 0; i < lhs.length && comparison == 0; i++) {
867 append(lhs[i], rhs[i]);
868 }
869 return this;
870 }
871
872 /**
873 * <p>Appends to the <code>builder</code> the deep comparison of
874 * two <code>double</code> arrays.</p>
875 *
876 * <ol>
877 * <li>Check if arrays are the same using <code>==</code></li>
878 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
879 * <li>Check array length, a shorter length array is less than a longer length array</li>
880 * <li>Check array contents element by element using {@link #append(double, double)}</li>
881 * </ol>
882 *
883 * @param lhs left-hand array
884 * @param rhs right-hand array
885 * @return this - used to chain append calls
886 */
887 public CompareToBuilder append(double[] lhs, double[] rhs) {
888 if (comparison != 0) {
889 return this;
890 }
891 if (lhs == rhs) {
892 return this;
893 }
894 if (lhs == null) {
895 comparison = -1;
896 return this;
897 }
898 if (rhs == null) {
899 comparison = +1;
900 return this;
901 }
902 if (lhs.length != rhs.length) {
903 comparison = (lhs.length < rhs.length) ? -1 : +1;
904 return this;
905 }
906 for (int i = 0; i < lhs.length && comparison == 0; i++) {
907 append(lhs[i], rhs[i]);
908 }
909 return this;
910 }
911
912 /**
913 * <p>Appends to the <code>builder</code> the deep comparison of
914 * two <code>float</code> arrays.</p>
915 *
916 * <ol>
917 * <li>Check if arrays are the same using <code>==</code></li>
918 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
919 * <li>Check array length, a shorter length array is less than a longer length array</li>
920 * <li>Check array contents element by element using {@link #append(float, float)}</li>
921 * </ol>
922 *
923 * @param lhs left-hand array
924 * @param rhs right-hand array
925 * @return this - used to chain append calls
926 */
927 public CompareToBuilder append(float[] lhs, float[] rhs) {
928 if (comparison != 0) {
929 return this;
930 }
931 if (lhs == rhs) {
932 return this;
933 }
934 if (lhs == null) {
935 comparison = -1;
936 return this;
937 }
938 if (rhs == null) {
939 comparison = +1;
940 return this;
941 }
942 if (lhs.length != rhs.length) {
943 comparison = (lhs.length < rhs.length) ? -1 : +1;
944 return this;
945 }
946 for (int i = 0; i < lhs.length && comparison == 0; i++) {
947 append(lhs[i], rhs[i]);
948 }
949 return this;
950 }
951
952 /**
953 * <p>Appends to the <code>builder</code> the deep comparison of
954 * two <code>boolean</code> arrays.</p>
955 *
956 * <ol>
957 * <li>Check if arrays are the same using <code>==</code></li>
958 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
959 * <li>Check array length, a shorter length array is less than a longer length array</li>
960 * <li>Check array contents element by element using {@link #append(boolean, boolean)}</li>
961 * </ol>
962 *
963 * @param lhs left-hand array
964 * @param rhs right-hand array
965 * @return this - used to chain append calls
966 */
967 public CompareToBuilder append(boolean[] lhs, boolean[] rhs) {
968 if (comparison != 0) {
969 return this;
970 }
971 if (lhs == rhs) {
972 return this;
973 }
974 if (lhs == null) {
975 comparison = -1;
976 return this;
977 }
978 if (rhs == null) {
979 comparison = +1;
980 return this;
981 }
982 if (lhs.length != rhs.length) {
983 comparison = (lhs.length < rhs.length) ? -1 : +1;
984 return this;
985 }
986 for (int i = 0; i < lhs.length && comparison == 0; i++) {
987 append(lhs[i], rhs[i]);
988 }
989 return this;
990 }
991
992 //-----------------------------------------------------------------------
993 /**
994 * Returns a negative integer, a positive integer, or zero as
995 * the <code>builder</code> has judged the "left-hand" side
996 * as less than, greater than, or equal to the "right-hand"
997 * side.
998 *
999 * @return final comparison result
1000 * @see #build()
1001 */
1002 public int toComparison() {
1003 return comparison;
1004 }
1005
1006 /**
1007 * Returns a negative Integer, a positive Integer, or zero as
1008 * the <code>builder</code> has judged the "left-hand" side
1009 * as less than, greater than, or equal to the "right-hand"
1010 * side.
1011 *
1012 * @return final comparison result as an Integer
1013 * @see #toComparison()
1014 * @since 3.0
1015 */
1016 public Integer build() {
1017 return Integer.valueOf(toComparison());
1018 }
1019 }
1020