001: /*
002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.binding.tests;
032:
033: import java.beans.PropertyChangeEvent;
034: import java.beans.PropertyVetoException;
035:
036: import junit.framework.TestCase;
037:
038: import com.jgoodies.binding.beans.*;
039: import com.jgoodies.binding.tests.beans.*;
040: import com.jgoodies.binding.tests.event.PropertyChangeReport;
041: import com.jgoodies.binding.tests.value.ValueHolderWithNewValueNull;
042: import com.jgoodies.binding.tests.value.ValueHolderWithOldAndNewValueNull;
043: import com.jgoodies.binding.tests.value.ValueHolderWithOldValueNull;
044: import com.jgoodies.binding.value.AbstractValueModel;
045: import com.jgoodies.binding.value.ValueHolder;
046: import com.jgoodies.binding.value.ValueModel;
047:
048: /**
049: * A test case for class {@link PropertyAdapter}.
050: *
051: * @author Karsten Lentzsch
052: * @version $Revision: 1.24 $
053: */
054: public final class PropertyAdapterTest extends TestCase {
055:
056: private TestBean model1;
057: private TestBean model2;
058:
059: /**
060: * @throws Exception in case of an unexpected problem
061: */
062: @Override
063: protected void setUp() throws Exception {
064: super .setUp();
065: model1 = new TestBean();
066: model2 = new TestBean();
067: }
068:
069: /**
070: * @throws Exception in case of an unexpected problem
071: */
072: @Override
073: protected void tearDown() throws Exception {
074: super .tearDown();
075: model1 = null;
076: model2 = null;
077: }
078:
079: // Constructor Tests ******************************************************
080:
081: /**
082: * Verifies that we can adapt observable and non-observable objects
083: * if we do not observe changes.
084: */
085: public void testConstructorsAcceptAllBeansWhenNotObserving() {
086: for (Object bean : BeanClasses.getBeans()) {
087: try {
088: new PropertyAdapter<Object>(bean, "property", false);
089: new PropertyAdapter<Object>(
090: new ValueHolder(bean, true), "property", false);
091: } catch (PropertyUnboundException ex) {
092: fail("Constructor must not try to observe with observeChanges == false");
093: }
094: }
095: }
096:
097: /**
098: * Verifies that we can adapt and observe observables.
099: */
100: public void testConstructorsAcceptToObserveObservables() {
101: for (Object bean : BeanClasses.getObservableBeans()) {
102: try {
103: new PropertyAdapter<Object>(bean, "property", true);
104: new PropertyAdapter<Object>(
105: new ValueHolder(bean, true), "property", true);
106: } catch (PropertyUnboundException ex) {
107: fail("Constructor failed to accept to observe an observable."
108: + "\nbean class="
109: + bean.getClass()
110: + "\nexception=" + ex);
111: }
112: }
113: }
114:
115: public void testConstructorRejectsNonIdentityCheckingBeanChannel() {
116: try {
117: new PropertyAdapter<Object>(new ValueHolder(null),
118: "aProperty");
119: fail("Constructor must reject bean channel that has the identity check feature disabled.");
120: } catch (IllegalArgumentException e) {
121: // The expected behavior
122: }
123: }
124:
125: /**
126: * Verifies that we cannot observe non-observables.
127: */
128: public void testConstructorsRejectToObserveObservables() {
129: for (Object bean : BeanClasses.getUnobservableBeans()) {
130: try {
131: new PropertyAdapter<Object>(bean, "property", true);
132: fail("Constructor must reject to observe non-observables.");
133: } catch (PropertyUnboundException ex) {
134: // The expected behavior
135: }
136: try {
137: new PropertyAdapter<Object>(
138: new ValueHolder(bean, true), "property", true);
139: fail("Constructor must reject to observe non-observables.");
140: } catch (PropertyUnboundException ex) {
141: // The expected behavior
142: }
143: }
144: }
145:
146: /**
147: * Verifies that we cannot observe non-observables.
148: */
149: public void testConstructorsAcceptsToObserveObjectsThatSupportBoundProperties() {
150: for (Object bean : BeanClasses.getBeans()) {
151: try {
152: boolean supportsBoundProperties = BeanUtils
153: .supportsBoundProperties(bean.getClass());
154: new PropertyAdapter<Object>(bean, "property",
155: supportsBoundProperties);
156: new PropertyAdapter<Object>(
157: new ValueHolder(bean, true), "property",
158: supportsBoundProperties);
159: } catch (PropertyUnboundException ex) {
160: fail("Constructor failed to accept to observe an observable."
161: + "\nbean class="
162: + bean.getClass()
163: + "\nexception=" + ex);
164: }
165: }
166: }
167:
168: public void testConstructorAcceptsNullBean() {
169: try {
170: new PropertyAdapter<Object>(null, "property", true);
171: } catch (NullPointerException ex) {
172: ex.printStackTrace();
173: fail("Constructor failed to accept a null bean."
174: + "\nexception=" + ex);
175: }
176: }
177:
178: public void testConstructorRejectsNullPropertyName() {
179: try {
180: new PropertyAdapter<TestBean>(new TestBean(), null, true);
181: fail("Constructor must reject a null property name.");
182: } catch (NullPointerException ex) {
183: // The expected behavior
184: }
185: }
186:
187: public void testConstructorRejectsEmptyPropertyName() {
188: try {
189: new PropertyAdapter<TestBean>(new TestBean(), "", true);
190: fail("Constructor must reject an empty property name.");
191: } catch (IllegalArgumentException ex) {
192: // The expected behavior
193: }
194: }
195:
196: // Testing Property Access ************************************************
197:
198: /**
199: */
200: public void testReadWriteProperties() {
201: TestBean bean = new TestBean();
202: bean.setReadWriteObjectProperty("initialValue");
203: bean.setReadWriteBooleanProperty(false);
204: bean.setReadWriteIntProperty(42);
205: ValueModel objectAdapter = new PropertyAdapter<TestBean>(bean,
206: "readWriteObjectProperty");
207: ValueModel booleanAdapter = new PropertyAdapter<TestBean>(bean,
208: "readWriteBooleanProperty");
209: ValueModel intAdapter = new PropertyAdapter<TestBean>(bean,
210: "readWriteIntProperty");
211: ValueModel integerAdapter = new PropertyAdapter<TestBean>(bean,
212: "readWriteIntegerProperty");
213:
214: // Adapter values equal the bean property values.
215: assertEquals(objectAdapter.getValue(), bean
216: .getReadWriteObjectProperty());
217: assertEquals(booleanAdapter.getValue(), Boolean.valueOf(bean
218: .isReadWriteBooleanProperty()));
219: assertEquals(intAdapter.getValue(), new Integer(bean
220: .getReadWriteIntProperty()));
221: assertEquals(integerAdapter.getValue(), bean
222: .getReadWriteIntegerProperty());
223:
224: Object objectValue = "testString";
225: Boolean booleanValue = Boolean.TRUE;
226: Integer integerValue = new Integer(43);
227:
228: objectAdapter.setValue(objectValue);
229: booleanAdapter.setValue(booleanValue);
230: intAdapter.setValue(integerValue);
231: integerAdapter.setValue(integerValue);
232: assertEquals(objectValue, bean.getReadWriteObjectProperty());
233: assertEquals(booleanValue, Boolean.valueOf(bean
234: .isReadWriteBooleanProperty()));
235: assertEquals(integerValue, new Integer(bean
236: .getReadWriteIntProperty()));
237: assertEquals(integerValue, bean.getReadWriteIntegerProperty());
238: }
239:
240: public void testReadWriteCustomProperties() {
241: CustomAccessBean bean = new CustomAccessBean();
242: bean.writeRWObjectProperty("initialValue");
243: bean.writeRWBooleanProperty(false);
244: bean.writeRWIntProperty(42);
245: ValueModel objectAdapter = new PropertyAdapter<CustomAccessBean>(
246: bean, "readWriteObjectProperty",
247: "readRWObjectProperty", "writeRWObjectProperty");
248: ValueModel booleanAdapter = new PropertyAdapter<CustomAccessBean>(
249: bean, "readWriteBooleanProperty",
250: "readRWBooleanProperty", "writeRWBooleanProperty");
251: ValueModel intAdapter = new PropertyAdapter<CustomAccessBean>(
252: bean, "readWriteIntProperty", "readRWIntProperty",
253: "writeRWIntProperty");
254:
255: // Adapter values equal the bean property values.
256: assertEquals(objectAdapter.getValue(), bean
257: .readRWObjectProperty());
258: assertEquals(booleanAdapter.getValue(), Boolean.valueOf(bean
259: .readRWBooleanProperty()));
260: assertEquals(intAdapter.getValue(), new Integer(bean
261: .readRWIntProperty()));
262:
263: Object objectValue = "testString";
264: Boolean booleanValue = Boolean.TRUE;
265: Integer integerValue = new Integer(43);
266:
267: objectAdapter.setValue(objectValue);
268: booleanAdapter.setValue(booleanValue);
269: intAdapter.setValue(integerValue);
270: assertEquals(objectValue, bean.readRWObjectProperty());
271: assertEquals(booleanValue, Boolean.valueOf(bean
272: .readRWBooleanProperty()));
273: assertEquals(integerValue,
274: new Integer(bean.readRWIntProperty()));
275: }
276:
277: public void testReadOnlyProperties() {
278: TestBean bean = new TestBean();
279: bean.readOnlyObjectProperty = "testString";
280: bean.readOnlyBooleanProperty = true;
281: bean.readOnlyIntProperty = 42;
282: ValueModel objectAdapter = new PropertyAdapter<TestBean>(bean,
283: "readOnlyObjectProperty");
284: ValueModel booleanAdapter = new PropertyAdapter<TestBean>(bean,
285: "readOnlyBooleanProperty");
286: ValueModel intAdapter = new PropertyAdapter<TestBean>(bean,
287: "readOnlyIntProperty");
288:
289: // Adapter values equal the bean property values.
290: assertEquals(objectAdapter.getValue(), bean
291: .getReadOnlyObjectProperty());
292: assertEquals(booleanAdapter.getValue(), Boolean.valueOf(bean
293: .isReadOnlyBooleanProperty()));
294: assertEquals(intAdapter.getValue(), new Integer(bean
295: .getReadOnlyIntProperty()));
296: try {
297: objectAdapter.setValue("some");
298: fail("Adapter must reject writing of read-only properties.");
299: } catch (UnsupportedOperationException ex) {
300: // The expected behavior
301: } catch (Exception e) {
302: fail("Unexpected exception=" + e);
303: }
304: }
305:
306: public void testReadOnlyCustomProperties() {
307: CustomAccessBean bean = new CustomAccessBean();
308: bean.readOnlyObjectProperty = "testString";
309: bean.readOnlyBooleanProperty = true;
310: bean.readOnlyIntProperty = 42;
311: ValueModel objectAdapter = new PropertyAdapter<CustomAccessBean>(
312: bean, "readOnlyObjectProperty", "readROObjectProperty",
313: null);
314: ValueModel booleanAdapter = new PropertyAdapter<CustomAccessBean>(
315: bean, "readOnlyBooleanProperty",
316: "readROBooleanProperty", null);
317: ValueModel intAdapter = new PropertyAdapter<CustomAccessBean>(
318: bean, "readOnlyIntProperty", "readROIntProperty", null);
319:
320: // Adapter values equal the bean property values.
321: assertEquals(objectAdapter.getValue(), bean
322: .readROObjectProperty());
323: assertEquals(booleanAdapter.getValue(), Boolean.valueOf(bean
324: .readROBooleanProperty()));
325: assertEquals(intAdapter.getValue(), new Integer(bean
326: .readROIntProperty()));
327: try {
328: objectAdapter.setValue("some");
329: fail("Adapter must reject writing of read-only properties.");
330: } catch (UnsupportedOperationException ex) {
331: // The expected behavior
332: } catch (Exception e) {
333: fail("Unexpected exception=" + e);
334: }
335: }
336:
337: /**
338: */
339: public void testWriteOnlyProperties() {
340: TestBean bean = new TestBean();
341: ValueModel objectAdapter = new PropertyAdapter<TestBean>(bean,
342: "writeOnlyObjectProperty");
343: ValueModel booleanAdapter = new PropertyAdapter<TestBean>(bean,
344: "writeOnlyBooleanProperty");
345: ValueModel intAdapter = new PropertyAdapter<TestBean>(bean,
346: "writeOnlyIntProperty");
347: Object objectValue = "testString";
348: Boolean booleanValue = Boolean.TRUE;
349: Integer integerValue = new Integer(42);
350: objectAdapter.setValue(objectValue);
351: booleanAdapter.setValue(booleanValue);
352: intAdapter.setValue(integerValue);
353: assertEquals(objectValue, bean.writeOnlyObjectProperty);
354: assertEquals(booleanValue, Boolean
355: .valueOf(bean.writeOnlyBooleanProperty));
356: assertEquals(integerValue, new Integer(
357: bean.writeOnlyIntProperty));
358: try {
359: objectAdapter.getValue();
360: fail("Adapter must reject to read a write-only property.");
361: } catch (UnsupportedOperationException ex) {
362: // The expected behavior
363: } catch (Exception e) {
364: fail("Unexpected exception=" + e);
365: }
366: }
367:
368: public void testWriteOnlyCustomProperties() {
369: CustomAccessBean bean = new CustomAccessBean();
370: ValueModel objectAdapter = new PropertyAdapter<CustomAccessBean>(
371: bean, "writeOnlyObjectProperty", null,
372: "writeWOObjectProperty");
373: ValueModel booleanAdapter = new PropertyAdapter<CustomAccessBean>(
374: bean, "writeOnlyBooleanProperty", null,
375: "writeWOBooleanProperty");
376: ValueModel intAdapter = new PropertyAdapter<CustomAccessBean>(
377: bean, "writeOnlyIntProperty", null,
378: "writeWOIntProperty");
379:
380: Object objectValue = "testString";
381: Boolean booleanValue = Boolean.TRUE;
382: Integer integerValue = new Integer(42);
383: objectAdapter.setValue(objectValue);
384: booleanAdapter.setValue(booleanValue);
385: intAdapter.setValue(integerValue);
386: assertEquals(objectValue, bean.writeOnlyObjectProperty);
387: assertEquals(booleanValue, Boolean
388: .valueOf(bean.writeOnlyBooleanProperty));
389: assertEquals(integerValue, new Integer(
390: bean.writeOnlyIntProperty));
391: try {
392: objectAdapter.getValue();
393: fail("Adapter must reject to read a write-only property.");
394: } catch (UnsupportedOperationException ex) {
395: // The expected behavior
396: } catch (Exception e) {
397: fail("Unexpected exception=" + e);
398: }
399: }
400:
401: /**
402: * Checks the write access to a constrained property without veto.
403: */
404: public void testWriteConstrainedPropertyWithoutVeto() {
405: TestBean bean = new TestBean();
406: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
407: bean, "constrainedProperty");
408: try {
409: bean.setConstrainedProperty("value1");
410: } catch (PropertyVetoException e1) {
411: fail("Unexpected veto for value1.");
412: }
413: assertEquals("Bean has the initial value1.", bean
414: .getConstrainedProperty(), "value1");
415:
416: adapter.setValue("value2a");
417: assertEquals("Bean now has the value2a.", bean
418: .getConstrainedProperty(), "value2a");
419: try {
420: adapter.setVetoableValue("value2b");
421: } catch (PropertyVetoException e) {
422: fail("Unexpected veto for value2b.");
423: }
424: assertEquals("Bean now has the value2b.", bean
425: .getConstrainedProperty(), "value2b");
426: }
427:
428: /**
429: * Checks the write access to a constrained property with veto.
430: */
431: public void testWriteConstrainedPropertyWithVeto() {
432: TestBean bean = new TestBean();
433: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
434: bean, "constrainedProperty");
435: try {
436: bean.setConstrainedProperty("value1");
437: } catch (PropertyVetoException e1) {
438: fail("Unexpected veto for value1.");
439: }
440: assertEquals("Bean has the initial value1.", bean
441: .getConstrainedProperty(), "value1");
442:
443: // Writing with a veto
444: bean.addVetoableChangeListener(new VetoableChangeRejector());
445:
446: adapter.setValue("value2a");
447: assertEquals("Bean still has the value1.", bean
448: .getConstrainedProperty(), "value1");
449: try {
450: adapter.setVetoableValue("value2b");
451: fail("Couldn't set the valid value1");
452: } catch (PropertyVetoException e) {
453: PropertyChangeEvent pce = e.getPropertyChangeEvent();
454: assertEquals("The veto's old value is value1.", pce
455: .getOldValue(), "value1");
456: assertEquals("The veto's new value is value2b.", pce
457: .getNewValue(), "value2b");
458: }
459: assertEquals(
460: "After setting value2b, the bean still has the value1.",
461: bean.getConstrainedProperty(), "value1");
462: }
463:
464: /**
465: * Verifies that the reader and writer can be located in different
466: * levels of a class hierarchy.
467: */
468: public void testReaderWriterSplittedInHierarchy() {
469: ReadWriteHierarchyBean bean = new ReadWriteHierarchyBean();
470: ValueModel adapter = new PropertyAdapter<ReadWriteHierarchyBean>(
471: bean, "property");
472: Object value1 = "Ewa";
473: String value2 = "Karsten";
474: adapter.setValue(value1);
475: assertEquals(value1, bean.getProperty());
476: bean.setProperty(value2);
477: assertEquals(value2, adapter.getValue());
478: }
479:
480: /**
481: * Tests access to properties that are described by a BeanInfo class.
482: */
483: public void testBeanInfoProperties() {
484: CustomBean bean = new CustomBean();
485: ValueModel adapter = new PropertyAdapter<CustomBean>(bean,
486: "readWriteObjectProperty");
487: Object value1 = "Ewa";
488: String value2 = "Karsten";
489: adapter.setValue(value1);
490: assertEquals(value1, bean.getReadWriteObjectProperty());
491: bean.setReadWriteObjectProperty(value2);
492: assertEquals(value2, adapter.getValue());
493:
494: try {
495: new PropertyAdapter<CustomBean>(bean,
496: "readWriteIntProperty");
497: fail("Adapter must not find properties that "
498: + "have been excluded by a custom BeanInfo.");
499: } catch (PropertyNotFoundException e) {
500: // The expected behavior
501: }
502: }
503:
504: public void testAbsentProperties() {
505: TestBean bean = new TestBean();
506: try {
507: new PropertyAdapter<TestBean>(bean, "absentObjectProperty");
508: fail("Adapter must reject an absent object property.");
509: } catch (PropertyNotFoundException ex) {
510: // The expected behavior
511: } catch (Exception e) {
512: fail("Unexpected exception=" + e);
513: }
514: try {
515: new PropertyAdapter<TestBean>(bean, "absentBooleanProperty");
516: fail("Adapter must reject an absent boolean property.");
517: } catch (PropertyNotFoundException ex) {
518: // The expected behavior
519: } catch (Exception e) {
520: fail("Unexpected exception=" + e);
521: }
522: try {
523: new PropertyAdapter<TestBean>(bean, "absentIntProperty");
524: fail("Adapter must reject an absent int property.");
525: } catch (PropertyNotFoundException ex) {
526: // The expected behavior
527: } catch (Exception e) {
528: fail("Unexpected exception=" + e);
529: }
530: }
531:
532: public void testIllegalPropertyAccess() {
533: TestBean bean = new TestBean();
534: try {
535: new PropertyAdapter<TestBean>(bean, "noAccess").getValue();
536: fail("Adapter must report read-access problems.");
537: } catch (PropertyAccessException ex) {
538: // The expected behavior
539: } catch (Exception e) {
540: fail("Unexpected exception=" + e);
541: }
542: try {
543: new PropertyAdapter<TestBean>(bean, "noAccess")
544: .setValue("Fails");
545: fail("Adapter must report write-access problems.");
546: } catch (PropertyAccessException ex) {
547: // The expected behavior
548: } catch (Exception e) {
549: fail("Unexpected exception=" + e);
550: }
551: try {
552: new PropertyAdapter<TestBean>(bean, "readWriteIntProperty")
553: .setValue(1967L);
554: fail("Adapter must report IllegalArgumentExceptions.");
555: } catch (PropertyAccessException ex) {
556: // The expected behavior
557: } catch (Exception e) {
558: fail("Unexpected exception=" + e);
559: }
560: }
561:
562: // Testing Update Notifications *******************************************
563:
564: public void testSetPropertySendsUpdates() {
565: AbstractValueModel adapter = new PropertyAdapter<TestBean>(
566: model1, "readWriteObjectProperty", true);
567: PropertyChangeReport changeReport = new PropertyChangeReport();
568: adapter.addPropertyChangeListener("value", changeReport);
569: model1.setReadWriteObjectProperty("Karsten");
570: assertEquals("First property change.", 1, changeReport
571: .eventCount());
572: model1.setReadWriteObjectProperty("Ewa");
573: assertEquals("Second property change.", 2, changeReport
574: .eventCount());
575: model1.setReadWriteObjectProperty(model1
576: .getReadWriteObjectProperty());
577: assertEquals("Property change repeated.", 2, changeReport
578: .eventCount());
579: }
580:
581: public void testSetValueSendsUpdates() {
582: AbstractValueModel adapter = new PropertyAdapter<TestBean>(
583: model1, "readWriteObjectProperty", true);
584: PropertyChangeReport changeReport = new PropertyChangeReport();
585: adapter.addPropertyChangeListener("value", changeReport);
586: adapter.setValue("Johannes");
587: assertEquals("Value change.", 1, changeReport.eventCount());
588: adapter.setValue(adapter.getValue());
589: assertEquals("Value set again.", 1, changeReport.eventCount());
590: }
591:
592: public void testListensOnlyToAdaptedProperty() {
593: AbstractValueModel adapter = new PropertyAdapter<TestBean>(
594: model1, "readWriteObjectProperty", true);
595: PropertyChangeReport changeReport = new PropertyChangeReport();
596: adapter.addPropertyChangeListener("value", changeReport);
597: model1.setReadWriteObjectProperty("Karsten");
598: assertEquals("Observed change.", 1, changeReport.eventCount());
599: model1.setReadWriteIntProperty(3);
600: assertEquals("Ignored change.", 1, changeReport.eventCount());
601: }
602:
603: public void testBeanChangeSendsUpdates() {
604: model1.setReadWriteObjectProperty("initialValue");
605: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
606: model1, "readWriteObjectProperty", true);
607: PropertyChangeReport changeReport = new PropertyChangeReport();
608: adapter.addPropertyChangeListener("value", changeReport);
609: adapter.setBean(model1);
610: assertEquals("First bean set.", 0, changeReport.eventCount());
611: adapter.setBean(new TestBean());
612: assertEquals("Second bean set.", 1, changeReport.eventCount());
613: }
614:
615: public void testBeanChangeIgnoresOldBeanNull() {
616: testBeanChangeIgnoresMissingOldOrNullValues(new ValueHolderWithOldValueNull(
617: null));
618: }
619:
620: public void testBeanChangeIgnoresNewBeanNull() {
621: testBeanChangeIgnoresMissingOldOrNullValues(new ValueHolderWithNewValueNull(
622: null));
623: }
624:
625: public void testBeanChangeIgnoresOldAndNewBeanNull() {
626: testBeanChangeIgnoresMissingOldOrNullValues(new ValueHolderWithOldAndNewValueNull(
627: null));
628: }
629:
630: private void testBeanChangeIgnoresMissingOldOrNullValues(
631: ValueModel beanChannel) {
632: TestBean bean1 = new TestBean();
633: TestBean bean2 = new TestBean();
634: beanChannel.setValue(bean1);
635: ValueModel adapter = new PropertyAdapter<TestBean>(beanChannel,
636: "readWriteObjectProperty", true);
637: PropertyChangeReport changeReport = new PropertyChangeReport();
638: adapter.addValueChangeListener(changeReport);
639: beanChannel.setValue(bean2);
640: bean1.setReadWriteObjectProperty("bean1value");
641: assertEquals("No event if modifying the old bean", 0,
642: changeReport.eventCount());
643: bean2.setReadWriteObjectProperty("bean2value");
644: assertEquals("Fires event if modifying the new bean", 1,
645: changeReport.eventCount());
646: }
647:
648: public void testMulticastAndNamedPropertyChangeEvents() {
649: AbstractValueModel adapter = new PropertyAdapter<TestBean>(
650: model1, "readWriteObjectProperty", true);
651: PropertyChangeReport changeReport = new PropertyChangeReport();
652: adapter.addPropertyChangeListener("value", changeReport);
653: model1.setReadWriteObjectProperty("Karsten");
654: assertEquals("Adapted property changed.", 1, changeReport
655: .eventCount());
656: model1.setReadWriteBooleanProperty(false);
657: assertEquals("Another property changed.", 1, changeReport
658: .eventCount());
659: model1.setReadWriteObjectProperties(null, false, 3);
660: assertEquals("Multiple properties changed.", 2, changeReport
661: .eventCount());
662: }
663:
664: public void testMulticastFiresProperNewValue() {
665: AbstractValueModel adapter = new PropertyAdapter<TestBean>(
666: model1, "readWriteObjectProperty", true);
667: PropertyChangeReport changeReport = new PropertyChangeReport();
668: adapter.addPropertyChangeListener("value", changeReport);
669:
670: Object theNewObjectValue = "The new value";
671: model1
672: .setReadWriteObjectProperties(theNewObjectValue, false,
673: 3);
674:
675: Object eventsNewValue = changeReport.lastNewValue();
676: assertEquals("Multicast fires proper new value .",
677: theNewObjectValue, eventsNewValue);
678: }
679:
680: // Misc *******************************************************************
681:
682: /**
683: * Checks that #setBean changes the bean and moves the
684: * PropertyChangeListeners to the new bean.
685: */
686: public void testSetBean() {
687: Object value1_1 = "value1.1";
688: Object value1_2 = "value1.2";
689: Object value2_1 = "value2.1";
690: Object value2_2 = "value2.2";
691: Object value2_3 = "value2.3";
692:
693: model1.setReadWriteObjectProperty(value1_1);
694: model2.setReadWriteObjectProperty(value2_1);
695: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
696: model1, "readWriteObjectProperty", true);
697: adapter.setBean(model2);
698:
699: assertSame("Bean has not been changed.", adapter.getBean(),
700: model2);
701:
702: assertSame(
703: "Bean change does not answer the new beans's value.",
704: adapter.getValue(), value2_1);
705:
706: adapter.setValue(value2_2);
707: assertSame("Bean change does not set the new bean's property.",
708: model2.getReadWriteObjectProperty(), value2_2);
709:
710: model1.setReadWriteObjectProperty(value1_2);
711: assertSame("Adapter listens to old bean after bean change.",
712: adapter.getValue(), value2_2);
713:
714: model2.setReadWriteObjectProperty(value2_3);
715: assertSame(
716: "Adapter does not listen to new bean after bean change.",
717: adapter.getValue(), value2_3);
718: }
719:
720: /**
721: * Tests that we can change the bean if we adapt a write-only property.
722: * Changing the bean normally calls the property's getter to request
723: * the old value that is used in the fired PropertyChangeEvent.
724: */
725: public void testSetBeanOnWriteOnlyProperty() {
726: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
727: model1, "writeOnlyObjectProperty", true);
728: adapter.setBean(model2);
729: }
730:
731: /**
732: * Tests that we can change the read/write state of the bean.
733: */
734: public void testSetBeanChangesReadWriteState() {
735: ReadWriteBean readWriteBean = new ReadWriteBean();
736: ReadOnlyBean readOnlyBean = new ReadOnlyBean();
737: WriteOnlyBean writeOnlyBean = new WriteOnlyBean();
738:
739: // From/to readWriteBean to all other read/write states
740: PropertyAdapter<Model> adapter = new PropertyAdapter<Model>(
741: readWriteBean, "property");
742: adapter.setBean(null);
743: adapter.setBean(readWriteBean);
744: adapter.setBean(readOnlyBean);
745: adapter.setBean(readWriteBean);
746: adapter.setBean(writeOnlyBean);
747: adapter.setBean(readWriteBean);
748:
749: // From/to writeOnlyBean to all other states
750: adapter.setBean(writeOnlyBean);
751: adapter.setBean(null);
752: adapter.setBean(writeOnlyBean);
753: adapter.setBean(readOnlyBean);
754: adapter.setBean(writeOnlyBean);
755:
756: // From/to readOnlyBean to all other states
757: adapter.setBean(readOnlyBean);
758: adapter.setBean(null);
759: adapter.setBean(readOnlyBean);
760: }
761:
762: /**
763: * Checks that bean changes are reported.
764: */
765: public void testBeanIsBoundProperty() {
766: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
767: model1, "readWriteObjectProperty");
768: PropertyChangeReport changeReport = new PropertyChangeReport();
769: adapter.addPropertyChangeListener("bean", changeReport);
770:
771: adapter.setBean(model2);
772: assertEquals("Bean changed.", 1, changeReport.eventCount());
773: adapter.setBean(model2);
774: assertEquals("Bean unchanged.", 1, changeReport.eventCount());
775: adapter.setBean(null);
776: assertEquals("Bean set to null.", 2, changeReport.eventCount());
777: adapter.setBean(model1);
778: assertEquals("Bean changed from null.", 3, changeReport
779: .eventCount());
780: }
781:
782: public void testBeanChangeFiresThreeBeanEvents() {
783: model1.setReadWriteObjectProperty("initialValue");
784: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
785: (TestBean) null, "readWriteObjectProperty", true);
786: PropertyChangeReport changeReport = new PropertyChangeReport();
787: adapter.addPropertyChangeListener(changeReport);
788:
789: adapter.setBean(model1);
790: assertEquals(
791: "Changing the bean fires three events: before, changing, after."
792: + "It also fires a change event.", 4,
793: changeReport.eventCount());
794: }
795:
796: public void testEqualBeanChangeFiresThreeBeanEvents() {
797: Object bean1 = new EquityTestBean("bean");
798: Object bean2 = new EquityTestBean("bean");
799: assertEquals("The two test beans are equal.", bean1, bean2);
800: assertNotSame("The two test beans are not the same.", bean1,
801: bean2);
802:
803: PropertyAdapter<Object> adapter1 = new PropertyAdapter<Object>(
804: bean1, "readWriteObjectProperty", true);
805: PropertyChangeReport changeReport1 = new PropertyChangeReport();
806: adapter1.addPropertyChangeListener(changeReport1);
807:
808: adapter1.setBean(bean2);
809: assertEquals(
810: "Changing the bean fires three events: before, changing, after.",
811: 3, changeReport1.eventCount());
812:
813: PropertyAdapter<Object> adapter2 = new PropertyAdapter<Object>(
814: null, "readWriteObjectProperty", true);
815: adapter2.setBean(bean1);
816: PropertyChangeReport changeReport2 = new PropertyChangeReport();
817: adapter2.addPropertyChangeListener(changeReport2);
818:
819: adapter2.setBean(bean2);
820: assertEquals(
821: "Changing the bean fires three events: before, changing, after.",
822: 3, changeReport2.eventCount());
823: }
824:
825: public void testChangedState() {
826: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
827: model1, "readWriteObjectProperty", true);
828:
829: assertEquals("The initial changed state is false.", false,
830: adapter.isChanged());
831: model1.setReadWriteObjectProperty("aBrandNewValue");
832: assertEquals(
833: "Changing the bean turns the changed state to true.",
834: true, adapter.isChanged());
835: adapter.resetChanged();
836: assertEquals(
837: "Resetting changes turns the changed state to false.",
838: false, adapter.isChanged());
839: model1.setReadWriteObjectProperty("anotherValue");
840: assertEquals(
841: "Changing the bean turns the changed state to true again.",
842: true, adapter.isChanged());
843: adapter.setBean(model2);
844: assertEquals("Changing the bean resets the changed state.",
845: false, adapter.isChanged());
846: }
847:
848: public void testChangedStateFiresEvents() {
849: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
850: model1, "readWriteObjectProperty", true);
851: PropertyChangeReport changeReport = new PropertyChangeReport();
852: adapter.addPropertyChangeListener("changed", changeReport);
853:
854: model1.setReadWriteObjectProperty("aBrandNewValue");
855: adapter.resetChanged();
856: model1.setReadWriteObjectProperty("anotherValue");
857: adapter.setBean(model2);
858: assertEquals("The changed state changed four times.", 4,
859: changeReport.eventCount());
860: }
861:
862: // Misc *******************************************************************
863:
864: /**
865: * Checks that the cached PropertyDescriptor is available when needed.
866: */
867: public void testPropertyDescriptorCache() {
868: ValueModel beanChannel = new ValueHolder(null, true);
869: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
870: beanChannel, "readWriteObjectProperty", true);
871:
872: beanChannel.setValue(new TestBean());
873: adapter.setValue("Test");
874: }
875:
876: }
|