001 /* 002 * Copyright 2002-2005 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016 package org.springframework.binding.value.support; 017 018 import org.springframework.binding.support.BeanPropertyAccessStrategy; 019 import org.springframework.binding.support.TestBean; 020 import org.springframework.binding.support.TestPropertyChangeListener; 021 import org.springframework.binding.value.CommitTrigger; 022 import org.springframework.binding.value.ValueChangeDetector; 023 import org.springframework.binding.value.ValueModel; 024 import org.springframework.richclient.application.ApplicationServicesLocator; 025 import org.springframework.richclient.test.SpringRichTestCase; 026 027 028 /** 029 * Tests class {@link BufferedValueModel}. 030 * 031 * @author Jeanette Winzenburg 032 * @author Karsten Lentzsch 033 * @author Oliver Hutchison 034 */ 035 public final class BufferedValueModelTests extends SpringRichTestCase { 036 037 private static final Object INITIAL_VALUE = "initial value"; 038 private static final Object RESET_VALUE = "reset value"; 039 040 private ValueModel wrapped; 041 private CommitTrigger commitTrigger; 042 043 protected void doSetUp() throws Exception { 044 wrapped = new ValueHolder(INITIAL_VALUE); 045 commitTrigger = new CommitTrigger(); 046 } 047 048 public void testGetWrappedValueModel() { 049 BufferedValueModel buffer = createDefaultBufferedValueModel(); 050 051 assertSame(wrapped, buffer.getWrappedValueModel()); 052 assertSame(wrapped, buffer.getInnerMostWrappedValueModel()); 053 054 ValueModel nestedValueModel = new AbstractValueModelWrapper(wrapped) {}; 055 buffer = new BufferedValueModel(nestedValueModel); 056 assertSame(nestedValueModel, buffer.getWrappedValueModel()); 057 assertSame(wrapped, buffer.getInnerMostWrappedValueModel()); 058 } 059 060 public void testReturnsWrappedValueIfNoValueAssigned() { 061 BufferedValueModel buffer = createDefaultBufferedValueModel(); 062 assertEquals( 063 "Buffer value equals the wrapped value before any changes.", 064 buffer.getValue(), 065 wrapped.getValue()); 066 067 wrapped.setValue("change1"); 068 assertEquals( 069 "Buffer value equals the wrapped value changes.", 070 buffer.getValue(), 071 wrapped.getValue()); 072 073 wrapped.setValue(null); 074 assertEquals( 075 "Buffer value equals the wrapped value changes.", 076 buffer.getValue(), 077 wrapped.getValue()); 078 079 wrapped.setValue("change2"); 080 assertEquals( 081 "Buffer value equals the wrapped value changes.", 082 buffer.getValue(), 083 wrapped.getValue()); 084 } 085 086 /** 087 * Tests that the BufferedValueModel returns the buffered values 088 * once a value has been assigned. 089 */ 090 public void testReturnsBufferedValueIfValueAssigned() { 091 BufferedValueModel buffer = createDefaultBufferedValueModel(); 092 093 Object newValue1 = wrapped.getValue(); 094 buffer.setValue(newValue1); 095 assertSame( 096 "Buffer value == new value once a value has been assigned.", 097 buffer.getValue(), 098 newValue1); 099 100 Object newValue2 = "change1"; 101 buffer.setValue(newValue2); 102 assertSame( 103 "Buffer value == new value once a value has been assigned.", 104 buffer.getValue(), 105 newValue2); 106 107 Object newValue3 = null; 108 buffer.setValue(newValue3); 109 assertSame( 110 "Buffer value == new value once a value has been assigned.", 111 buffer.getValue(), 112 newValue3); 113 114 Object newValue4 = "change2"; 115 buffer.setValue(newValue4); 116 assertSame( 117 "Buffer value == new value once a value has been assigned.", 118 buffer.getValue(), 119 newValue4); 120 } 121 122 public void testDetectedWrappedValueChangeIfValueAssigned() { 123 BufferedValueModel buffer = createDefaultBufferedValueModel(); 124 125 Object newValue1 = "change1"; 126 buffer.setValue(newValue1); 127 wrapped.setValue("change3"); 128 assertSame( 129 "Buffer value == new value once a value has been assigned.", 130 buffer.getValue(), 131 "change3"); 132 wrapped.setValue(newValue1); 133 assertSame( 134 "Buffer value == new value once a value has been assigned.", 135 buffer.getValue(), 136 newValue1); 137 wrapped.setValue(null); 138 assertSame( 139 "Buffer value == new value once a value has been assigned.", 140 buffer.getValue(), 141 null); 142 } 143 144 /** 145 * Tests that the BufferedValueModel returns the wrapped's values 146 * after a commit. 147 */ 148 public void testReturnsWrappedValueAfterCommit() { 149 BufferedValueModel buffer = createDefaultBufferedValueModel(); 150 buffer.setValue("change1"); // shall buffer now 151 commit(); 152 assertEquals( 153 "Buffer value equals the wrapped value after a commit.", 154 buffer.getValue(), 155 wrapped.getValue()); 156 157 wrapped.setValue("change2"); 158 assertEquals( 159 "Buffer value equals the wrapped value after a commit.", 160 buffer.getValue(), 161 wrapped.getValue()); 162 163 wrapped.setValue(buffer.getValue()); 164 assertEquals( 165 "Buffer value equals the wrapped value after a commit.", 166 buffer.getValue(), 167 wrapped.getValue()); 168 } 169 170 /** 171 * Tests that the BufferedValueModel returns the wrapped's values 172 * after a flush. 173 */ 174 public void testReturnsWrappedValueAfterFlush() { 175 BufferedValueModel buffer = createDefaultBufferedValueModel(); 176 buffer.setValue("change1"); // shall buffer now 177 revert(); 178 assertEquals( 179 "Buffer value equals the wrapped value after a flush.", 180 wrapped.getValue(), 181 buffer.getValue()); 182 183 wrapped.setValue("change2"); 184 assertEquals( 185 "Buffer value equals the wrapped value after a flush.", 186 wrapped.getValue(), 187 buffer.getValue()); 188 } 189 190 191 // Testing Proper Value Commit and Flush ********************************** 192 193 /** 194 * Tests the core of the buffering feature: buffer modifications 195 * do not affect the wrapped before a commit. 196 */ 197 public void testWrappedValuesUnchangedBeforeCommit() { 198 BufferedValueModel buffer = createDefaultBufferedValueModel(); 199 Object oldWrappedValue = wrapped.getValue(); 200 buffer.setValue("changedBuffer1"); 201 assertEquals( 202 "Buffer changes do not change the wrapped value before a commit.", 203 wrapped.getValue(), 204 oldWrappedValue 205 ); 206 buffer.setValue(null); 207 assertEquals( 208 "Buffer changes do not change the wrapped value before a commit.", 209 wrapped.getValue(), 210 oldWrappedValue 211 ); 212 buffer.setValue(oldWrappedValue); 213 assertEquals( 214 "Buffer changes do not change the wrapped value before a commit.", 215 wrapped.getValue(), 216 oldWrappedValue 217 ); 218 buffer.setValue("changedBuffer2"); 219 assertEquals( 220 "Buffer changes do not change the wrapped value before a commit.", 221 wrapped.getValue(), 222 oldWrappedValue 223 ); 224 } 225 226 /** 227 * Tests the core of a commit: buffer changes are written through on commit 228 * and change the wrapped value. 229 */ 230 public void testCommitChangesWrappedValue() { 231 BufferedValueModel buffer = createDefaultBufferedValueModel(); 232 Object oldWrappedValue = wrapped.getValue(); 233 Object newValue1 = "change1"; 234 buffer.setValue(newValue1); 235 assertEquals( 236 "Wrapped value is unchanged before the first commit.", 237 wrapped.getValue(), 238 oldWrappedValue); 239 commit(); 240 assertEquals( 241 "Wrapped value is the new value after the first commit.", 242 wrapped.getValue(), 243 newValue1); 244 245 // Set the buffer to the current wrapped value to check whether 246 // the starts buffering, even if there's no value difference. 247 Object newValue2 = wrapped.getValue(); 248 buffer.setValue(newValue2); 249 commit(); 250 assertEquals( 251 "Wrapped value is the new value after the second commit.", 252 wrapped.getValue(), 253 newValue2); 254 } 255 256 /** 257 * Tests the core of a flush action: buffer changes are overridden 258 * by wrapped changes after a flush. 259 */ 260 public void testFlushResetsTheBufferedValue() { 261 BufferedValueModel buffer = createDefaultBufferedValueModel(); 262 Object newValue1 = "new value1"; 263 buffer.setValue(newValue1); 264 assertSame( 265 "Buffer value reflects changes before the first flush.", 266 buffer.getValue(), 267 newValue1); 268 revert(); 269 assertEquals( 270 "Buffer value is the wrapped value after the first flush.", 271 buffer.getValue(), 272 wrapped.getValue()); 273 274 // Set the buffer to the current wrapped value to check whether 275 // the starts buffering, even if there's no value difference. 276 Object newValue2 = wrapped.getValue(); 277 buffer.setValue(newValue2); 278 assertSame( 279 "Buffer value reflects changes before the flush.", 280 buffer.getValue(), 281 newValue2); 282 revert(); 283 assertEquals( 284 "Buffer value is the wrapped value after the second flush.", 285 buffer.getValue(), 286 wrapped.getValue()); 287 } 288 289 // Tests a Proper Buffering State ***************************************** 290 291 /** 292 * Tests that a buffer isn't buffering as long as no value has been assigned. 293 */ 294 public void testIsNotBufferingIfNoValueAssigned() { 295 BufferedValueModel buffer = createDefaultBufferedValueModel(); 296 assertFalse( 297 "Initially the buffer does not buffer.", 298 buffer.isBuffering()); 299 300 Object newValue = "change1"; 301 wrapped.setValue(newValue); 302 assertFalse( 303 "Wrapped changes do not affect the buffering state.", 304 buffer.isBuffering()); 305 306 wrapped.setValue(null); 307 assertFalse( 308 "Wrapped change to null does not affect the buffering state.", 309 buffer.isBuffering()); 310 } 311 312 /** 313 * Tests that the buffer is buffering once a value has been assigned. 314 */ 315 public void testIsBufferingIfValueAssigned() { 316 BufferedValueModel buffer = createDefaultBufferedValueModel(); 317 buffer.setValue("change1"); 318 assertTrue( 319 "Setting a value (even the wrapped's value) turns on buffering.", 320 buffer.isBuffering()); 321 322 buffer.setValue("change2"); 323 assertTrue( 324 "Changing the value doesn't affect the buffering state.", 325 buffer.isBuffering()); 326 327 buffer.setValue(wrapped.getValue()); 328 assertTrue( 329 "Resetting the value to the wrapped's value should affect buffering.", 330 !buffer.isBuffering()); 331 } 332 333 /** 334 * Tests that the buffer is not buffering after a commit. 335 */ 336 public void testIsNotBufferingAfterCommit() { 337 BufferedValueModel buffer = createDefaultBufferedValueModel(); 338 buffer.setValue("change1"); 339 commit(); 340 assertFalse( 341 "The buffer does not buffer after a commit.", 342 buffer.isBuffering()); 343 344 Object newValue = "change1"; 345 wrapped.setValue(newValue); 346 assertFalse( 347 "The buffer does not buffer after a commit and wrapped change1.", 348 buffer.isBuffering()); 349 350 wrapped.setValue(null); 351 assertFalse( 352 "The buffer does not buffer after a commit and wrapped change2.", 353 buffer.isBuffering()); 354 } 355 356 /** 357 * Tests that the buffer is not buffering after a flush. 358 */ 359 public void testIsNotBufferingAfterFlush() { 360 BufferedValueModel buffer = createDefaultBufferedValueModel(); 361 buffer.setValue("change1"); 362 revert(); 363 assertFalse( 364 "The buffer does not buffer after a flush.", 365 buffer.isBuffering()); 366 367 Object newValue = "change1"; 368 wrapped.setValue(newValue); 369 assertFalse( 370 "The buffer does not buffer after a flush and wrapped change1.", 371 buffer.isBuffering()); 372 373 wrapped.setValue(null); 374 assertFalse( 375 "The buffer does not buffer after a flush and wrapped change2.", 376 buffer.isBuffering()); 377 } 378 379 /** 380 * Tests that changing the buffering state fires changes of 381 * the <i>buffering</i> property. 382 */ 383 public void testFiresBufferingChanges() { 384 BufferedValueModel buffer = createDefaultBufferedValueModel(); 385 386 TestPropertyChangeListener pcl = new TestPropertyChangeListener(BufferedValueModel.BUFFERING_PROPERTY); 387 buffer.addPropertyChangeListener(BufferedValueModel.BUFFERING_PROPERTY, pcl); 388 389 assertEquals("Initial state.", 0, pcl.eventCount()); 390 buffer.getValue(); 391 assertEquals("Reading initial value.", 0, pcl.eventCount()); 392 buffer.setCommitTrigger(null); 393 buffer.setCommitTrigger(commitTrigger); 394 assertEquals("After commit trigger change.", 0, pcl.eventCount()); 395 396 buffer.setValue("now buffering"); 397 assertEquals("After setting the first value.", 1, pcl.eventCount()); 398 buffer.setValue("still buffering"); 399 assertEquals("After setting the second value.", 1, pcl.eventCount()); 400 buffer.getValue(); 401 assertEquals("Reading buffered value.", 1, pcl.eventCount()); 402 403 wrapped.setValue(buffer.getValue()); 404 assertEquals("Changing wrapped to same as buffer.", 2, pcl.eventCount()); 405 406 commit(); 407 assertEquals("After committing.", 2, pcl.eventCount()); 408 buffer.getValue(); 409 assertEquals("Reading unbuffered value.", 2, pcl.eventCount()); 410 411 buffer.setValue("buffering again"); 412 assertEquals("After second buffering switch.", 3, pcl.eventCount()); 413 revert(); 414 assertEquals("After flushing.", 4, pcl.eventCount()); 415 buffer.getValue(); 416 assertEquals("Reading unbuffered value.", 4, pcl.eventCount()); 417 418 buffer.setValue("before real commit"); 419 assertEquals("With new change to be committed", 5, pcl.eventCount()); 420 commit(); 421 assertEquals("With new change committed", 6, pcl.eventCount()); 422 } 423 424 public void testSetValueSendsProperValueChangeEvents() { 425 Object obj1 = new Integer(1); 426 Object obj2a = new Integer(2); 427 Object obj2b = new Integer(2); 428 testSetValueSendsProperEvents(null, obj1, true); 429 testSetValueSendsProperEvents(obj1, null, true); 430 testSetValueSendsProperEvents(obj1, obj1, false); 431 testSetValueSendsProperEvents(obj1, obj2a, true); 432 testSetValueSendsProperEvents(obj2a, obj2b, false); 433 testSetValueSendsProperEvents(null, null, false); 434 } 435 436 437 public void testValueChangeSendsProperValueChangeEvents() { 438 Object obj1 = new Integer(1); 439 Object obj2a = new Integer(2); 440 Object obj2b = new Integer(2); 441 testValueChangeSendsProperEvents(null, obj1, true); 442 testValueChangeSendsProperEvents(obj1, null, true); 443 testValueChangeSendsProperEvents(obj1, obj1, false); 444 testValueChangeSendsProperEvents(obj1, obj2a, true); 445 testValueChangeSendsProperEvents(obj2a, obj2b, false); 446 testValueChangeSendsProperEvents(null, null, false); 447 448 // Now replace the default value change detector with one that 449 // only uses true equivalence. 450 ValueChangeDetector oldVCD = (ValueChangeDetector)ApplicationServicesLocator.services().getService(ValueChangeDetector.class); 451 getApplicationServices().setValueChangeDetector(new StrictEquivalenceValueChangeDetector()); 452 testValueChangeSendsProperEvents(null, obj1, true); 453 testValueChangeSendsProperEvents(obj1, null, true); 454 testValueChangeSendsProperEvents(obj1, obj1, false); 455 testValueChangeSendsProperEvents(obj1, obj2a, true); 456 testValueChangeSendsProperEvents(obj2a, obj2b, true); 457 testValueChangeSendsProperEvents(null, null, false); 458 459 getApplicationServices().setValueChangeDetector(oldVCD); 460 } 461 462 463 // Commit Trigger Tests ************************************************* 464 465 466 /** 467 * Checks that #setCommitTrigger changes the commit trigger. 468 */ 469 public void testCommitTriggerChange() { 470 CommitTrigger trigger1 = new CommitTrigger(); 471 CommitTrigger trigger2 = new CommitTrigger(); 472 473 BufferedValueModel buffer = new BufferedValueModel(wrapped, trigger1); 474 assertSame( 475 "Commit trigger has been changed.", 476 buffer.getCommitTrigger(), 477 trigger1); 478 479 buffer.setCommitTrigger(trigger2); 480 assertSame( 481 "Commit trigger has been changed.", 482 buffer.getCommitTrigger(), 483 trigger2); 484 485 buffer.setCommitTrigger(null); 486 assertSame( 487 "Commit trigger has been changed.", 488 buffer.getCommitTrigger(), 489 null); 490 } 491 492 /** 493 * Checks and verifies that commit and flush events are driven 494 * by the current commit trigger. 495 */ 496 public void testListensToCurrentCommitTrigger() { 497 CommitTrigger trigger1 = new CommitTrigger(); 498 CommitTrigger trigger2 = new CommitTrigger(); 499 500 BufferedValueModel buffer = new BufferedValueModel(wrapped, trigger1); 501 buffer.setValue("change1"); 502 Object wrappedValue = wrapped.getValue(); 503 Object bufferedValue = buffer.getValue(); 504 trigger2.commit(); 505 assertEquals( 506 "Changing the unrelated trigger2 to commit has no effect on the wrapped.", 507 wrapped.getValue(), 508 wrappedValue); 509 assertSame( 510 "Changing the unrelated trigger2 to commit has no effect on the buffer.", 511 buffer.getValue(), 512 bufferedValue); 513 514 trigger2.revert(); 515 assertEquals( 516 "Changing the unrelated trigger2 to revert has no effect on the wrapped.", 517 wrapped.getValue(), 518 wrappedValue); 519 assertSame( 520 "Changing the unrelated trigger2 to revert has no effect on the buffer.", 521 buffer.getValue(), 522 bufferedValue); 523 524 // Change the commit trigger to trigger2. 525 buffer.setCommitTrigger(trigger2); 526 assertSame( 527 "Commit trigger has been changed.", 528 buffer.getCommitTrigger(), 529 trigger2); 530 531 trigger1.commit(); 532 assertEquals( 533 "Changing the unrelated trigger1 to commit has no effect on the wrapped.", 534 wrapped.getValue(), 535 wrappedValue); 536 assertSame( 537 "Changing the unrelated trigger1 to commit has no effect on the buffer.", 538 buffer.getValue(), 539 bufferedValue); 540 541 trigger1.revert(); 542 assertEquals( 543 "Changing the unrelated trigger1 to revert has no effect on the wrapped.", 544 wrapped.getValue(), 545 wrappedValue); 546 assertSame( 547 "Changing the unrelated trigger1 to revert has no effect on the buffer.", 548 buffer.getValue(), 549 bufferedValue); 550 551 // Commit using trigger2. 552 trigger2.commit(); 553 assertEquals( 554 "Changing the current trigger2 to commit commits the buffered value.", 555 buffer.getValue(), 556 wrapped.getValue()); 557 558 buffer.setValue("change2"); 559 wrappedValue = wrapped.getValue(); 560 trigger2.revert(); 561 assertEquals( 562 "Changing the current trigger2 to revert flushes the buffered value.", 563 buffer.getValue(), 564 wrapped.getValue()); 565 assertEquals( 566 "Changing the current trigger2 to revert flushes the buffered value.", 567 buffer.getValue(), 568 wrappedValue); 569 } 570 571 572 // Tests Proper Update Notifications ************************************** 573 574 /** 575 * Checks that wrapped changes fire value changes 576 * if no value has been assigned. 577 */ 578 public void testPropagatesWrappedChangesIfNoValueAssigned() { 579 BufferedValueModel buffer = createDefaultBufferedValueModel(); 580 TestPropertyChangeListener pcl = new TestPropertyChangeListener(ValueModel.VALUE_PROPERTY); 581 buffer.addValueChangeListener(pcl); 582 583 wrapped.setValue("change1"); 584 assertEquals("Value change.", 1, pcl.eventCount()); 585 586 wrapped.setValue(null); 587 assertEquals("Value change.", 2, pcl.eventCount()); 588 589 wrapped.setValue("change2"); 590 assertEquals("Value change.", 3, pcl.eventCount()); 591 592 wrapped.setValue(buffer.getValue()); 593 assertEquals("No value change.", 3, pcl.eventCount()); 594 } 595 596 /** 597 * Tests that wrapped changes are propagated once a value has 598 * been assigned, i.e. the buffer is buffering. 599 */ 600 public void testIgnoresWrappedChangesIfValueAssigned() { 601 BufferedValueModel buffer = createDefaultBufferedValueModel(); 602 TestPropertyChangeListener pcl = new TestPropertyChangeListener(ValueModel.VALUE_PROPERTY); 603 buffer.addValueChangeListener(pcl); 604 605 buffer.setValue("new buffer"); 606 wrapped.setValue("change1"); 607 assertEquals("Value change.", 2, pcl.eventCount()); 608 609 buffer.setValue("new buffer"); 610 wrapped.setValue(null); 611 assertEquals("Value change.", 4, pcl.eventCount()); 612 613 buffer.setValue("new buffer"); 614 wrapped.setValue("change2"); 615 assertEquals("Value change.", 6, pcl.eventCount()); 616 617 buffer.setValue("new buffer"); 618 wrapped.setValue(buffer.getValue()); // won't fire event 619 assertEquals("No value change.", 7, pcl.eventCount()); 620 } 621 622 /** 623 * Checks and verifies that a commit fires no value change. 624 */ 625 public void testCommitFiresNoChangeOnSameOldAndNewValues() { 626 BufferedValueModel buffer = createDefaultBufferedValueModel(); 627 buffer.setValue("value1"); 628 TestPropertyChangeListener pcl = new TestPropertyChangeListener(ValueModel.VALUE_PROPERTY); 629 buffer.addValueChangeListener(pcl); 630 631 assertEquals("No initial change.", 0, pcl.eventCount()); 632 commit(); 633 assertEquals("First commit: no change.", 0, pcl.eventCount()); 634 635 buffer.setValue("value2"); 636 assertEquals("Setting a value: a change.", 1, pcl.eventCount()); 637 commit(); 638 assertEquals("Second commit: no change.", 1, pcl.eventCount()); 639 } 640 641 public void testCommitFiresChangeOnDifferentOldAndNewValues() { 642 BufferedValueModel buffer = createDefaultBufferedValueModel( 643 new ToUpperCaseStringHolder()); 644 buffer.setValue("initialValue"); 645 TestPropertyChangeListener pcl = new TestPropertyChangeListener(ValueModel.VALUE_PROPERTY); 646 buffer.addValueChangeListener(pcl); 647 buffer.setValue("value1"); 648 assertEquals("One event fired", 649 1, 650 pcl.eventCount()); 651 assertEquals("First value set.", 652 "value1", 653 pcl.lastEvent().getNewValue()); 654 commit(); 655 assertEquals("Commit fires if the wrapped modifies the value.", 656 2, 657 pcl.eventCount()); 658 assertEquals("Old value is the buffered value.", 659 "value1", 660 pcl.lastEvent().getOldValue()); 661 assertEquals("New value is the modified value.", 662 "VALUE1", 663 pcl.lastEvent().getNewValue()); 664 } 665 666 /** 667 * Tests that a flush event fires a value change if and only if 668 * the flushed value does not equal the buffered value. 669 */ 670 public void testFlushFiresTrueValueChanges() { 671 BufferedValueModel buffer = createDefaultBufferedValueModel(); 672 TestPropertyChangeListener pcl = new TestPropertyChangeListener(ValueModel.VALUE_PROPERTY); 673 674 wrapped.setValue("new wrapped"); 675 buffer.setValue("new buffer"); 676 buffer.addValueChangeListener(pcl); 677 revert(); 678 assertEquals("First flush changes value.", 1, pcl.eventCount()); 679 680 buffer.setValue(wrapped.getValue()); 681 assertEquals("Resetting value: no change.", 1, pcl.eventCount()); 682 revert(); 683 assertEquals("Second flush: no change.", 1, pcl.eventCount()); 684 685 buffer.setValue("new buffer2"); 686 assertEquals("Second value change.", 2, pcl.eventCount()); 687 wrapped.setValue("new wrapped2"); 688 assertEquals("Setting new wrapped value: no change.", 3, pcl.eventCount()); 689 buffer.setValue(wrapped.getValue()); 690 assertEquals("Third value change.", 3, pcl.eventCount()); 691 revert(); 692 assertEquals("Third flush: no change.", 3, pcl.eventCount()); 693 } 694 695 // Misc Tests ************************************************************* 696 697 /** 698 * Tests read actions on a read-only model. 699 */ 700 public void testReadOnly() { 701 TestBean bean = new TestBean(); 702 ValueModel readOnlyModel = new BeanPropertyAccessStrategy(bean).getPropertyValueModel("readOnly"); 703 BufferedValueModel buffer = new BufferedValueModel(readOnlyModel, commitTrigger); 704 705 assertSame( 706 "Can read values from a read-only model.", 707 buffer.getValue(), 708 readOnlyModel.getValue()); 709 710 Object newValue1 = "new value"; 711 buffer.setValue(newValue1); 712 assertSame( 713 "Can read values from a read-only model when buffering.", 714 buffer.getValue(), 715 newValue1); 716 717 revert(); 718 assertSame( 719 "Can read values from a read-only model after a flush.", 720 buffer.getValue(), 721 bean.getReadOnly()); 722 723 buffer.setValue("new value2"); 724 try { 725 commit(); 726 fail("Cannot commit to a read-only model."); 727 } catch (Exception e) { 728 // The expected behavior 729 } 730 } 731 732 // Test Implementations *************************************************** 733 734 private void testSetValueSendsProperEvents(Object oldValue, Object newValue, boolean eventExpected) { 735 BufferedValueModel valueModel = 736 new BufferedValueModel(new ValueHolder(oldValue), new CommitTrigger()); 737 testSendsProperEvents(valueModel, oldValue, newValue, eventExpected); 738 } 739 740 private void testValueChangeSendsProperEvents(Object oldValue, Object newValue, boolean eventExpected) { 741 BufferedValueModel defaultModel = createDefaultBufferedValueModel(); 742 defaultModel.setValue(oldValue); 743 testSendsProperEvents(defaultModel, oldValue, newValue, eventExpected); 744 } 745 746 private void testSendsProperEvents(BufferedValueModel valueModel, Object oldValue, Object newValue, boolean eventExpected) { 747 TestPropertyChangeListener pcl = new TestPropertyChangeListener(ValueModel.VALUE_PROPERTY); 748 valueModel.addValueChangeListener(pcl); 749 int expectedEventCount = eventExpected ? 1 : 0; 750 751 valueModel.setValue(newValue); 752 assertEquals( 753 "Expected event count after ( " + 754 oldValue + " -> " + newValue + ").", 755 expectedEventCount, 756 pcl.eventCount()); 757 if (eventExpected) { 758 assertEquals("Event's old value.", oldValue, pcl.lastEvent().getOldValue()); 759 assertEquals("Event's new value.", newValue, pcl.lastEvent().getNewValue()); 760 } 761 } 762 763 764 // Helper Code ************************************************************ 765 766 private void commit() { 767 commitTrigger.commit(); 768 } 769 770 private void revert() { 771 commitTrigger.revert(); 772 } 773 774 private BufferedValueModel createDefaultBufferedValueModel() { 775 wrapped.setValue(RESET_VALUE); 776 return new BufferedValueModel(wrapped, commitTrigger); 777 } 778 779 private BufferedValueModel createDefaultBufferedValueModel(ValueModel wrapped) { 780 wrapped.setValue(RESET_VALUE); 781 return new BufferedValueModel(wrapped, commitTrigger); 782 } 783 784 // A String typed ValueModel that modifies set values to uppercase. 785 private static class ToUpperCaseStringHolder extends AbstractValueModel { 786 787 private String text; 788 789 public Object getValue() { 790 return text; 791 } 792 793 public void setValue(Object newValue) { 794 String newText = ((String) newValue).toUpperCase(); 795 Object oldText = text; 796 text = newText; 797 fireValueChange(oldText, newText); 798 } 799 800 } 801 802 /** 803 * This class is used to test alternate value change detection methods. 804 */ 805 private static class StrictEquivalenceValueChangeDetector implements ValueChangeDetector { 806 public boolean hasValueChanged(Object oldValue, Object newValue) { 807 return oldValue != newValue; 808 } 809 } 810 811 }