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 }