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 */ 017package org.apache.commons.lang3.builder; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.List; 022 023import org.apache.commons.lang3.ArrayUtils; 024 025/** 026 * <p> 027 * Assists in implementing {@link Diffable#diff(Object)} methods. 028 * </p> 029 * 030 * <p> 031 * To use this class, write code as follows: 032 * </p> 033 * 034 * <pre> 035 * public class Person implements Diffable<Person> { 036 * String name; 037 * int age; 038 * boolean smoker; 039 * 040 * ... 041 * 042 * public DiffResult diff(Person obj) { 043 * // No need for null check, as NullPointerException correct if obj is null 044 * return new DiffBuilder(this, obj, ToStringStyle.SHORT_PREFIX_STYLE) 045 * .append("name", this.name, obj.name) 046 * .append("age", this.age, obj.age) 047 * .append("smoker", this.smoker, obj.smoker) 048 * .build(); 049 * } 050 * } 051 * </pre> 052 * 053 * <p> 054 * The {@code ToStringStyle} passed to the constructor is embedded in the 055 * returned {@code DiffResult} and influences the style of the 056 * {@code DiffResult.toString()} method. This style choice can be overridden by 057 * calling {@link DiffResult#toString(ToStringStyle)}. 058 * </p> 059 * 060 * @since 3.3 061 * @see Diffable 062 * @see Diff 063 * @see DiffResult 064 * @see ToStringStyle 065 */ 066public class DiffBuilder implements Builder<DiffResult> { 067 068 private final List<Diff<?>> diffs; 069 private final boolean objectsTriviallyEqual; 070 private final Object left; 071 private final Object right; 072 private final ToStringStyle style; 073 074 /** 075 * <p> 076 * Constructs a builder for the specified objects with the specified style. 077 * </p> 078 * 079 * <p> 080 * If {@code lhs == rhs} or {@code lhs.equals(rhs)} then the builder will 081 * not evaluate any calls to {@code append(...)} and will return an empty 082 * {@link DiffResult} when {@link #build()} is executed. 083 * </p> 084 * 085 * @param lhs 086 * {@code this} object 087 * @param rhs 088 * the object to diff against 089 * @param style 090 * the style will use when outputting the objects, {@code null} 091 * uses the default 092 * @param testTriviallyEqual 093 * If true, this will test if lhs and rhs are the same or equal. 094 * All of the append(fieldName, lhs, rhs) methods will abort 095 * without creating a field {@link Diff} if the trivially equal 096 * test is enabled and returns true. The result of this test 097 * is never changed throughout the life of this {@link DiffBuilder}. 098 * @throws IllegalArgumentException 099 * if {@code lhs} or {@code rhs} is {@code null} 100 * @since 3.4 101 */ 102 public DiffBuilder(final Object lhs, final Object rhs, 103 final ToStringStyle style, final boolean testTriviallyEqual) { 104 105 if (lhs == null) { 106 throw new IllegalArgumentException("lhs cannot be null"); 107 } 108 if (rhs == null) { 109 throw new IllegalArgumentException("rhs cannot be null"); 110 } 111 112 this.diffs = new ArrayList<Diff<?>>(); 113 this.left = lhs; 114 this.right = rhs; 115 this.style = style; 116 117 // Don't compare any fields if objects equal 118 this.objectsTriviallyEqual = testTriviallyEqual && (lhs == rhs || lhs.equals(rhs)); 119 } 120 121 /** 122 * <p> 123 * Constructs a builder for the specified objects with the specified style. 124 * </p> 125 * 126 * <p> 127 * If {@code lhs == rhs} or {@code lhs.equals(rhs)} then the builder will 128 * not evaluate any calls to {@code append(...)} and will return an empty 129 * {@link DiffResult} when {@link #build()} is executed. 130 * </p> 131 * 132 * <p> 133 * This delegates to {@link #DiffBuilder(Object, Object, ToStringStyle, boolean)} 134 * with the testTriviallyEqual flag enabled. 135 * </p> 136 * 137 * @param lhs 138 * {@code this} object 139 * @param rhs 140 * the object to diff against 141 * @param style 142 * the style will use when outputting the objects, {@code null} 143 * uses the default 144 * @throws IllegalArgumentException 145 * if {@code lhs} or {@code rhs} is {@code null} 146 */ 147 public DiffBuilder(final Object lhs, final Object rhs, 148 final ToStringStyle style) { 149 150 this(lhs, rhs, style, true); 151 } 152 153 /** 154 * <p> 155 * Test if two {@code boolean}s are equal. 156 * </p> 157 * 158 * @param fieldName 159 * the field name 160 * @param lhs 161 * the left hand {@code boolean} 162 * @param rhs 163 * the right hand {@code boolean} 164 * @return this 165 * @throws IllegalArgumentException 166 * if field name is {@code null} 167 */ 168 public DiffBuilder append(final String fieldName, final boolean lhs, 169 final boolean rhs) { 170 if (fieldName == null) { 171 throw new IllegalArgumentException("Field name cannot be null"); 172 } 173 174 if (objectsTriviallyEqual) { 175 return this; 176 } 177 if (lhs != rhs) { 178 diffs.add(new Diff<Boolean>(fieldName) { 179 private static final long serialVersionUID = 1L; 180 181 @Override 182 public Boolean getLeft() { 183 return Boolean.valueOf(lhs); 184 } 185 186 @Override 187 public Boolean getRight() { 188 return Boolean.valueOf(rhs); 189 } 190 }); 191 } 192 return this; 193 } 194 195 /** 196 * <p> 197 * Test if two {@code boolean[]}s are equal. 198 * </p> 199 * 200 * @param fieldName 201 * the field name 202 * @param lhs 203 * the left hand {@code boolean[]} 204 * @param rhs 205 * the right hand {@code boolean[]} 206 * @return this 207 * @throws IllegalArgumentException 208 * if field name is {@code null} 209 */ 210 public DiffBuilder append(final String fieldName, final boolean[] lhs, 211 final boolean[] rhs) { 212 if (fieldName == null) { 213 throw new IllegalArgumentException("Field name cannot be null"); 214 } 215 if (objectsTriviallyEqual) { 216 return this; 217 } 218 if (!Arrays.equals(lhs, rhs)) { 219 diffs.add(new Diff<Boolean[]>(fieldName) { 220 private static final long serialVersionUID = 1L; 221 222 @Override 223 public Boolean[] getLeft() { 224 return ArrayUtils.toObject(lhs); 225 } 226 227 @Override 228 public Boolean[] getRight() { 229 return ArrayUtils.toObject(rhs); 230 } 231 }); 232 } 233 return this; 234 } 235 236 /** 237 * <p> 238 * Test if two {@code byte}s are equal. 239 * </p> 240 * 241 * @param fieldName 242 * the field name 243 * @param lhs 244 * the left hand {@code byte} 245 * @param rhs 246 * the right hand {@code byte} 247 * @return this 248 * @throws IllegalArgumentException 249 * if field name is {@code null} 250 */ 251 public DiffBuilder append(final String fieldName, final byte lhs, 252 final byte rhs) { 253 if (fieldName == null) { 254 throw new IllegalArgumentException("Field name cannot be null"); 255 } 256 if (objectsTriviallyEqual) { 257 return this; 258 } 259 if (lhs != rhs) { 260 diffs.add(new Diff<Byte>(fieldName) { 261 private static final long serialVersionUID = 1L; 262 263 @Override 264 public Byte getLeft() { 265 return Byte.valueOf(lhs); 266 } 267 268 @Override 269 public Byte getRight() { 270 return Byte.valueOf(rhs); 271 } 272 }); 273 } 274 return this; 275 } 276 277 /** 278 * <p> 279 * Test if two {@code byte[]}s are equal. 280 * </p> 281 * 282 * @param fieldName 283 * the field name 284 * @param lhs 285 * the left hand {@code byte[]} 286 * @param rhs 287 * the right hand {@code byte[]} 288 * @return this 289 * @throws IllegalArgumentException 290 * if field name is {@code null} 291 */ 292 public DiffBuilder append(final String fieldName, final byte[] lhs, 293 final byte[] rhs) { 294 if (fieldName == null) { 295 throw new IllegalArgumentException("Field name cannot be null"); 296 } 297 298 if (objectsTriviallyEqual) { 299 return this; 300 } 301 if (!Arrays.equals(lhs, rhs)) { 302 diffs.add(new Diff<Byte[]>(fieldName) { 303 private static final long serialVersionUID = 1L; 304 305 @Override 306 public Byte[] getLeft() { 307 return ArrayUtils.toObject(lhs); 308 } 309 310 @Override 311 public Byte[] getRight() { 312 return ArrayUtils.toObject(rhs); 313 } 314 }); 315 } 316 return this; 317 } 318 319 /** 320 * <p> 321 * Test if two {@code char}s are equal. 322 * </p> 323 * 324 * @param fieldName 325 * the field name 326 * @param lhs 327 * the left hand {@code char} 328 * @param rhs 329 * the right hand {@code char} 330 * @return this 331 * @throws IllegalArgumentException 332 * if field name is {@code null} 333 */ 334 public DiffBuilder append(final String fieldName, final char lhs, 335 final char rhs) { 336 if (fieldName == null) { 337 throw new IllegalArgumentException("Field name cannot be null"); 338 } 339 340 if (objectsTriviallyEqual) { 341 return this; 342 } 343 if (lhs != rhs) { 344 diffs.add(new Diff<Character>(fieldName) { 345 private static final long serialVersionUID = 1L; 346 347 @Override 348 public Character getLeft() { 349 return Character.valueOf(lhs); 350 } 351 352 @Override 353 public Character getRight() { 354 return Character.valueOf(rhs); 355 } 356 }); 357 } 358 return this; 359 } 360 361 /** 362 * <p> 363 * Test if two {@code char[]}s are equal. 364 * </p> 365 * 366 * @param fieldName 367 * the field name 368 * @param lhs 369 * the left hand {@code char[]} 370 * @param rhs 371 * the right hand {@code char[]} 372 * @return this 373 * @throws IllegalArgumentException 374 * if field name is {@code null} 375 */ 376 public DiffBuilder append(final String fieldName, final char[] lhs, 377 final char[] rhs) { 378 if (fieldName == null) { 379 throw new IllegalArgumentException("Field name cannot be null"); 380 } 381 382 if (objectsTriviallyEqual) { 383 return this; 384 } 385 if (!Arrays.equals(lhs, rhs)) { 386 diffs.add(new Diff<Character[]>(fieldName) { 387 private static final long serialVersionUID = 1L; 388 389 @Override 390 public Character[] getLeft() { 391 return ArrayUtils.toObject(lhs); 392 } 393 394 @Override 395 public Character[] getRight() { 396 return ArrayUtils.toObject(rhs); 397 } 398 }); 399 } 400 return this; 401 } 402 403 /** 404 * <p> 405 * Test if two {@code double}s are equal. 406 * </p> 407 * 408 * @param fieldName 409 * the field name 410 * @param lhs 411 * the left hand {@code double} 412 * @param rhs 413 * the right hand {@code double} 414 * @return this 415 * @throws IllegalArgumentException 416 * if field name is {@code null} 417 */ 418 public DiffBuilder append(final String fieldName, final double lhs, 419 final double rhs) { 420 if (fieldName == null) { 421 throw new IllegalArgumentException("Field name cannot be null"); 422 } 423 424 if (objectsTriviallyEqual) { 425 return this; 426 } 427 if (Double.doubleToLongBits(lhs) != Double.doubleToLongBits(rhs)) { 428 diffs.add(new Diff<Double>(fieldName) { 429 private static final long serialVersionUID = 1L; 430 431 @Override 432 public Double getLeft() { 433 return Double.valueOf(lhs); 434 } 435 436 @Override 437 public Double getRight() { 438 return Double.valueOf(rhs); 439 } 440 }); 441 } 442 return this; 443 } 444 445 /** 446 * <p> 447 * Test if two {@code double[]}s are equal. 448 * </p> 449 * 450 * @param fieldName 451 * the field name 452 * @param lhs 453 * the left hand {@code double[]} 454 * @param rhs 455 * the right hand {@code double[]} 456 * @return this 457 * @throws IllegalArgumentException 458 * if field name is {@code null} 459 */ 460 public DiffBuilder append(final String fieldName, final double[] lhs, 461 final double[] rhs) { 462 if (fieldName == null) { 463 throw new IllegalArgumentException("Field name cannot be null"); 464 } 465 466 if (objectsTriviallyEqual) { 467 return this; 468 } 469 if (!Arrays.equals(lhs, rhs)) { 470 diffs.add(new Diff<Double[]>(fieldName) { 471 private static final long serialVersionUID = 1L; 472 473 @Override 474 public Double[] getLeft() { 475 return ArrayUtils.toObject(lhs); 476 } 477 478 @Override 479 public Double[] getRight() { 480 return ArrayUtils.toObject(rhs); 481 } 482 }); 483 } 484 return this; 485 } 486 487 /** 488 * <p> 489 * Test if two {@code float}s are equal. 490 * </p> 491 * 492 * @param fieldName 493 * the field name 494 * @param lhs 495 * the left hand {@code float} 496 * @param rhs 497 * the right hand {@code float} 498 * @return this 499 * @throws IllegalArgumentException 500 * if field name is {@code null} 501 */ 502 public DiffBuilder append(final String fieldName, final float lhs, 503 final float rhs) { 504 if (fieldName == null) { 505 throw new IllegalArgumentException("Field name cannot be null"); 506 } 507 508 if (objectsTriviallyEqual) { 509 return this; 510 } 511 if (Float.floatToIntBits(lhs) != Float.floatToIntBits(rhs)) { 512 diffs.add(new Diff<Float>(fieldName) { 513 private static final long serialVersionUID = 1L; 514 515 @Override 516 public Float getLeft() { 517 return Float.valueOf(lhs); 518 } 519 520 @Override 521 public Float getRight() { 522 return Float.valueOf(rhs); 523 } 524 }); 525 } 526 return this; 527 } 528 529 /** 530 * <p> 531 * Test if two {@code float[]}s are equal. 532 * </p> 533 * 534 * @param fieldName 535 * the field name 536 * @param lhs 537 * the left hand {@code float[]} 538 * @param rhs 539 * the right hand {@code float[]} 540 * @return this 541 * @throws IllegalArgumentException 542 * if field name is {@code null} 543 */ 544 public DiffBuilder append(final String fieldName, final float[] lhs, 545 final float[] rhs) { 546 if (fieldName == null) { 547 throw new IllegalArgumentException("Field name cannot be null"); 548 } 549 550 if (objectsTriviallyEqual) { 551 return this; 552 } 553 if (!Arrays.equals(lhs, rhs)) { 554 diffs.add(new Diff<Float[]>(fieldName) { 555 private static final long serialVersionUID = 1L; 556 557 @Override 558 public Float[] getLeft() { 559 return ArrayUtils.toObject(lhs); 560 } 561 562 @Override 563 public Float[] getRight() { 564 return ArrayUtils.toObject(rhs); 565 } 566 }); 567 } 568 return this; 569 } 570 571 /** 572 * <p> 573 * Test if two {@code int}s are equal. 574 * </p> 575 * 576 * @param fieldName 577 * the field name 578 * @param lhs 579 * the left hand {@code int} 580 * @param rhs 581 * the right hand {@code int} 582 * @return this 583 * @throws IllegalArgumentException 584 * if field name is {@code null} 585 */ 586 public DiffBuilder append(final String fieldName, final int lhs, 587 final int rhs) { 588 if (fieldName == null) { 589 throw new IllegalArgumentException("Field name cannot be null"); 590 } 591 592 if (objectsTriviallyEqual) { 593 return this; 594 } 595 if (lhs != rhs) { 596 diffs.add(new Diff<Integer>(fieldName) { 597 private static final long serialVersionUID = 1L; 598 599 @Override 600 public Integer getLeft() { 601 return Integer.valueOf(lhs); 602 } 603 604 @Override 605 public Integer getRight() { 606 return Integer.valueOf(rhs); 607 } 608 }); 609 } 610 return this; 611 } 612 613 /** 614 * <p> 615 * Test if two {@code int[]}s are equal. 616 * </p> 617 * 618 * @param fieldName 619 * the field name 620 * @param lhs 621 * the left hand {@code int[]} 622 * @param rhs 623 * the right hand {@code int[]} 624 * @return this 625 * @throws IllegalArgumentException 626 * if field name is {@code null} 627 */ 628 public DiffBuilder append(final String fieldName, final int[] lhs, 629 final int[] rhs) { 630 if (fieldName == null) { 631 throw new IllegalArgumentException("Field name cannot be null"); 632 } 633 634 if (objectsTriviallyEqual) { 635 return this; 636 } 637 if (!Arrays.equals(lhs, rhs)) { 638 diffs.add(new Diff<Integer[]>(fieldName) { 639 private static final long serialVersionUID = 1L; 640 641 @Override 642 public Integer[] getLeft() { 643 return ArrayUtils.toObject(lhs); 644 } 645 646 @Override 647 public Integer[] getRight() { 648 return ArrayUtils.toObject(rhs); 649 } 650 }); 651 } 652 return this; 653 } 654 655 /** 656 * <p> 657 * Test if two {@code long}s are equal. 658 * </p> 659 * 660 * @param fieldName 661 * the field name 662 * @param lhs 663 * the left hand {@code long} 664 * @param rhs 665 * the right hand {@code long} 666 * @return this 667 * @throws IllegalArgumentException 668 * if field name is {@code null} 669 */ 670 public DiffBuilder append(final String fieldName, final long lhs, 671 final long rhs) { 672 if (fieldName == null) { 673 throw new IllegalArgumentException("Field name cannot be null"); 674 } 675 676 if (objectsTriviallyEqual) { 677 return this; 678 } 679 if (lhs != rhs) { 680 diffs.add(new Diff<Long>(fieldName) { 681 private static final long serialVersionUID = 1L; 682 683 @Override 684 public Long getLeft() { 685 return Long.valueOf(lhs); 686 } 687 688 @Override 689 public Long getRight() { 690 return Long.valueOf(rhs); 691 } 692 }); 693 } 694 return this; 695 } 696 697 /** 698 * <p> 699 * Test if two {@code long[]}s are equal. 700 * </p> 701 * 702 * @param fieldName 703 * the field name 704 * @param lhs 705 * the left hand {@code long[]} 706 * @param rhs 707 * the right hand {@code long[]} 708 * @return this 709 * @throws IllegalArgumentException 710 * if field name is {@code null} 711 */ 712 public DiffBuilder append(final String fieldName, final long[] lhs, 713 final long[] rhs) { 714 if (fieldName == null) { 715 throw new IllegalArgumentException("Field name cannot be null"); 716 } 717 718 if (objectsTriviallyEqual) { 719 return this; 720 } 721 if (!Arrays.equals(lhs, rhs)) { 722 diffs.add(new Diff<Long[]>(fieldName) { 723 private static final long serialVersionUID = 1L; 724 725 @Override 726 public Long[] getLeft() { 727 return ArrayUtils.toObject(lhs); 728 } 729 730 @Override 731 public Long[] getRight() { 732 return ArrayUtils.toObject(rhs); 733 } 734 }); 735 } 736 return this; 737 } 738 739 /** 740 * <p> 741 * Test if two {@code short}s are equal. 742 * </p> 743 * 744 * @param fieldName 745 * the field name 746 * @param lhs 747 * the left hand {@code short} 748 * @param rhs 749 * the right hand {@code short} 750 * @return this 751 * @throws IllegalArgumentException 752 * if field name is {@code null} 753 */ 754 public DiffBuilder append(final String fieldName, final short lhs, 755 final short rhs) { 756 if (fieldName == null) { 757 throw new IllegalArgumentException("Field name cannot be null"); 758 } 759 760 if (objectsTriviallyEqual) { 761 return this; 762 } 763 if (lhs != rhs) { 764 diffs.add(new Diff<Short>(fieldName) { 765 private static final long serialVersionUID = 1L; 766 767 @Override 768 public Short getLeft() { 769 return Short.valueOf(lhs); 770 } 771 772 @Override 773 public Short getRight() { 774 return Short.valueOf(rhs); 775 } 776 }); 777 } 778 return this; 779 } 780 781 /** 782 * <p> 783 * Test if two {@code short[]}s are equal. 784 * </p> 785 * 786 * @param fieldName 787 * the field name 788 * @param lhs 789 * the left hand {@code short[]} 790 * @param rhs 791 * the right hand {@code short[]} 792 * @return this 793 * @throws IllegalArgumentException 794 * if field name is {@code null} 795 */ 796 public DiffBuilder append(final String fieldName, final short[] lhs, 797 final short[] rhs) { 798 if (fieldName == null) { 799 throw new IllegalArgumentException("Field name cannot be null"); 800 } 801 802 if (objectsTriviallyEqual) { 803 return this; 804 } 805 if (!Arrays.equals(lhs, rhs)) { 806 diffs.add(new Diff<Short[]>(fieldName) { 807 private static final long serialVersionUID = 1L; 808 809 @Override 810 public Short[] getLeft() { 811 return ArrayUtils.toObject(lhs); 812 } 813 814 @Override 815 public Short[] getRight() { 816 return ArrayUtils.toObject(rhs); 817 } 818 }); 819 } 820 return this; 821 } 822 823 /** 824 * <p> 825 * Test if two {@code Objects}s are equal. 826 * </p> 827 * 828 * @param fieldName 829 * the field name 830 * @param lhs 831 * the left hand {@code Object} 832 * @param rhs 833 * the right hand {@code Object} 834 * @return this 835 * @throws IllegalArgumentException 836 * if field name is {@code null} 837 */ 838 public DiffBuilder append(final String fieldName, final Object lhs, 839 final Object rhs) { 840 if (fieldName == null) { 841 throw new IllegalArgumentException("Field name cannot be null"); 842 } 843 if (objectsTriviallyEqual) { 844 return this; 845 } 846 if (lhs == rhs) { 847 return this; 848 } 849 850 Object objectToTest; 851 if (lhs != null) { 852 objectToTest = lhs; 853 } else { 854 // rhs cannot be null, as lhs != rhs 855 objectToTest = rhs; 856 } 857 858 if (objectToTest.getClass().isArray()) { 859 if (objectToTest instanceof boolean[]) { 860 return append(fieldName, (boolean[]) lhs, (boolean[]) rhs); 861 } 862 if (objectToTest instanceof byte[]) { 863 return append(fieldName, (byte[]) lhs, (byte[]) rhs); 864 } 865 if (objectToTest instanceof char[]) { 866 return append(fieldName, (char[]) lhs, (char[]) rhs); 867 } 868 if (objectToTest instanceof double[]) { 869 return append(fieldName, (double[]) lhs, (double[]) rhs); 870 } 871 if (objectToTest instanceof float[]) { 872 return append(fieldName, (float[]) lhs, (float[]) rhs); 873 } 874 if (objectToTest instanceof int[]) { 875 return append(fieldName, (int[]) lhs, (int[]) rhs); 876 } 877 if (objectToTest instanceof long[]) { 878 return append(fieldName, (long[]) lhs, (long[]) rhs); 879 } 880 if (objectToTest instanceof short[]) { 881 return append(fieldName, (short[]) lhs, (short[]) rhs); 882 } 883 884 return append(fieldName, (Object[]) lhs, (Object[]) rhs); 885 } 886 887 // Not array type 888 if (lhs != null && lhs.equals(rhs)) { 889 return this; 890 } 891 892 diffs.add(new Diff<Object>(fieldName) { 893 private static final long serialVersionUID = 1L; 894 895 @Override 896 public Object getLeft() { 897 return lhs; 898 } 899 900 @Override 901 public Object getRight() { 902 return rhs; 903 } 904 }); 905 906 return this; 907 } 908 909 /** 910 * <p> 911 * Test if two {@code Object[]}s are equal. 912 * </p> 913 * 914 * @param fieldName 915 * the field name 916 * @param lhs 917 * the left hand {@code Object[]} 918 * @param rhs 919 * the right hand {@code Object[]} 920 * @return this 921 * @throws IllegalArgumentException 922 * if field name is {@code null} 923 */ 924 public DiffBuilder append(final String fieldName, final Object[] lhs, 925 final Object[] rhs) { 926 if (fieldName == null) { 927 throw new IllegalArgumentException("Field name cannot be null"); 928 } 929 if (objectsTriviallyEqual) { 930 return this; 931 } 932 933 if (!Arrays.equals(lhs, rhs)) { 934 diffs.add(new Diff<Object[]>(fieldName) { 935 private static final long serialVersionUID = 1L; 936 937 @Override 938 public Object[] getLeft() { 939 return lhs; 940 } 941 942 @Override 943 public Object[] getRight() { 944 return rhs; 945 } 946 }); 947 } 948 949 return this; 950 } 951 952 /** 953 * <p> 954 * Append diffs from another {@code DiffResult}. 955 * </p> 956 * 957 * <p> 958 * This method is useful if you want to compare properties which are 959 * themselves Diffable and would like to know which specific part of 960 * it is different. 961 * </p> 962 * 963 * <pre> 964 * public class Person implements Diffable<Person> { 965 * String name; 966 * Address address; // implements Diffable<Address> 967 * 968 * ... 969 * 970 * public DiffResult diff(Person obj) { 971 * return new DiffBuilder(this, obj, ToStringStyle.SHORT_PREFIX_STYLE) 972 * .append("name", this.name, obj.name) 973 * .append("address", this.address.diff(obj.address)) 974 * .build(); 975 * } 976 * } 977 * </pre> 978 * 979 * @param fieldName 980 * the field name 981 * @param diffResult 982 * the {@code DiffResult} to append 983 * @return this 984 * @throws IllegalArgumentException 985 * if field name is {@code null} 986 * @since 3.5 987 */ 988 public DiffBuilder append(final String fieldName, 989 final DiffResult diffResult) { 990 if (fieldName == null) { 991 throw new IllegalArgumentException("Field name cannot be null"); 992 } 993 if (diffResult == null) { 994 throw new IllegalArgumentException("Diff result cannot be null"); 995 } 996 if (objectsTriviallyEqual) { 997 return this; 998 } 999 1000 for (Diff<?> diff : diffResult.getDiffs()) { 1001 append(fieldName + "." + diff.getFieldName(), 1002 diff.getLeft(), diff.getRight()); 1003 } 1004 1005 return this; 1006 } 1007 1008 /** 1009 * <p> 1010 * Builds a {@link DiffResult} based on the differences appended to this 1011 * builder. 1012 * </p> 1013 * 1014 * @return a {@code DiffResult} containing the differences between the two 1015 * objects. 1016 */ 1017 @Override 1018 public DiffResult build() { 1019 return new DiffResult(left, right, diffs, style); 1020 } 1021 1022}