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.util.ArrayList;
034: import java.util.Collections;
035: import java.util.LinkedList;
036: import java.util.List;
037:
038: import junit.framework.TestCase;
039:
040: import com.jgoodies.binding.beans.BeanAdapter;
041: import com.jgoodies.binding.beans.PropertyAdapter;
042: import com.jgoodies.binding.tests.beans.TestBean;
043: import com.jgoodies.binding.tests.event.PropertyChangeReport;
044: import com.jgoodies.binding.value.AbstractValueModel;
045: import com.jgoodies.binding.value.BufferedValueModel;
046: import com.jgoodies.binding.value.Trigger;
047: import com.jgoodies.binding.value.ValueModel;
048:
049: /**
050: * Tests old and new values when the bean, value or subject changes in
051: * BeanAdapter, PropertyAdapter, PresentationModel and BufferedValueModel.
052: *
053: * @author Karsten Lentzsch
054: * @version $Revision: 1.12 $
055: */
056: public final class ValueChangeTest extends TestCase {
057:
058: private TestBean model1;
059: private TestBean model2;
060:
061: // Setup ******************************************************************
062:
063: /**
064: * @throws Exception in case of an unexpected problem
065: */
066: @Override
067: protected void setUp() throws Exception {
068: super .setUp();
069: model1 = new TestBean();
070: model2 = new TestBean();
071: }
072:
073: /**
074: * @throws Exception in case of an unexpected problem
075: */
076: @Override
077: protected void tearDown() throws Exception {
078: super .tearDown();
079: model1 = null;
080: model2 = null;
081: }
082:
083: // Public Tests ***********************************************************
084:
085: public void testBeanAdapterBeanChange() {
086: Object[][] pairs = createOldAndNewValuePairs();
087: for (Object[] element : pairs) {
088: Object bean1Value = element[0];
089: Object bean2Value = element[1];
090: testBeanAdapterBeanChange(bean1Value, bean2Value);
091: }
092: }
093:
094: public void testBeanAdapterValueChange() {
095: Object[][] pairs = createOldAndNewValuePairs();
096: for (Object[] element : pairs) {
097: Object value1 = element[0];
098: Object value2 = element[1];
099: testBeanAdapterValueChange(value1, value2);
100: }
101: }
102:
103: public void testPropertyAdapterBeanChange() {
104: Object[][] pairs = createOldAndNewValuePairs();
105: for (Object[] element : pairs) {
106: Object bean1Value = element[0];
107: Object bean2Value = element[1];
108: testPropertyAdapterBeanChange(bean1Value, bean2Value);
109: }
110: }
111:
112: public void testPropertyAdapterValueChange() {
113: Object[][] pairs = createOldAndNewValuePairs();
114: for (Object[] element : pairs) {
115: Object value1 = element[0];
116: Object value2 = element[1];
117: testPropertyAdapterValueChange(value1, value2);
118: }
119: }
120:
121: public void testBufferedValueModelSubjectChange() {
122: Object[][] pairs = createOldAndNewValuePairs();
123: for (Object[] element : pairs) {
124: Object value1 = element[0];
125: Object value2 = element[1];
126: testBufferedValueModelSubjectChange(value1, value2);
127: }
128: }
129:
130: public void testBufferedValueModelValueChange() {
131: Object[][] pairs = createOldAndNewValuePairs();
132: for (Object[] element : pairs) {
133: Object value1 = element[0];
134: Object value2 = element[1];
135: testBufferedValueModelSubjectValueChange(value1, value2);
136: }
137: }
138:
139: // Test Implementations ***************************************************
140:
141: private void testBeanAdapterBeanChange(Object value1, Object value2) {
142: model1.setReadWriteObjectProperty(value1);
143: model2.setReadWriteObjectProperty(value2);
144:
145: BeanAdapter<TestBean> adapter = new BeanAdapter<TestBean>(
146: (TestBean) null, true);
147: AbstractValueModel valueModel = adapter
148: .getValueModel("readWriteObjectProperty");
149:
150: PropertyChangeReport changeReport = new PropertyChangeReport();
151: valueModel.addPropertyChangeListener("value", changeReport);
152: Object eventsOldValue;
153: Object eventsNewValue;
154: int expectedEventCount = 0;
155:
156: adapter.setBean(model1);
157: boolean firesEventFromNullToModel1 = requiresPropertyChangeEvent(
158: null, value1);
159: if (firesEventFromNullToModel1) {
160: expectedEventCount++;
161: }
162: assertEquals("Expected event count after null -> model1 ("
163: + null + " -> " + value1 + ").", expectedEventCount,
164: changeReport.eventCount());
165: if (firesEventFromNullToModel1) {
166: eventsOldValue = changeReport.lastOldValue();
167: eventsNewValue = changeReport.lastNewValue();
168: assertEquals(
169: "null-> model1 change fires proper old value.",
170: null, eventsOldValue);
171: assertEquals(
172: "null-> model1 change fires proper new value.",
173: value1, eventsNewValue);
174: }
175:
176: adapter.setBean(model2);
177: boolean firesEventFromModel1ToModel2 = requiresPropertyChangeEvent(
178: value1, value2);
179: if (firesEventFromModel1ToModel2) {
180: expectedEventCount++;
181: }
182: assertEquals("Expected event count after model1 -> model2 ("
183: + value1 + " -> " + value2 + ").", expectedEventCount,
184: changeReport.eventCount());
185: if (firesEventFromModel1ToModel2) {
186: eventsOldValue = changeReport.lastOldValue();
187: eventsNewValue = changeReport.lastNewValue();
188: assertEquals(
189: "model1 -> model2 change fires proper old value.",
190: value1, eventsOldValue);
191: assertEquals(
192: "model1 -> model2 change fires proper new value.",
193: value2, eventsNewValue);
194: }
195:
196: adapter.setBean(null);
197: boolean firesEventFromModel2ToNull = requiresPropertyChangeEvent(
198: value2, null);
199: if (firesEventFromModel2ToNull) {
200: expectedEventCount++;
201: }
202: assertEquals("Expected event count after model2 -> null ("
203: + value2 + " -> " + null + ").", expectedEventCount,
204: changeReport.eventCount());
205: if (firesEventFromModel2ToNull) {
206: eventsOldValue = changeReport.lastOldValue();
207: eventsNewValue = changeReport.lastNewValue();
208: assertEquals(
209: "model2 -> null change fires proper old value.",
210: value2, eventsOldValue);
211: assertEquals(
212: "model2 -> null change fires proper new value.",
213: null, eventsNewValue);
214: }
215: }
216:
217: private void testBeanAdapterValueChange(Object value1, Object value2) {
218: BeanAdapter<TestBean> adapter = new BeanAdapter<TestBean>(
219: model1, true);
220: testValueChange(value1, value2, adapter
221: .getValueModel("readWriteObjectProperty"));
222: }
223:
224: private void testPropertyAdapterBeanChange(Object value1,
225: Object value2) {
226: model1.setReadWriteObjectProperty(value1);
227: model2.setReadWriteObjectProperty(value2);
228:
229: PropertyAdapter<TestBean> adapter = new PropertyAdapter<TestBean>(
230: (TestBean) null, "readWriteObjectProperty", true);
231: PropertyChangeReport changeReport = new PropertyChangeReport();
232: adapter.addPropertyChangeListener("value", changeReport);
233: Object eventsOldValue;
234: Object eventsNewValue;
235: int expectedEventCount = 0;
236:
237: adapter.setBean(model1);
238: boolean firesEventFromNullToModel1 = requiresPropertyChangeEvent(
239: null, value1);
240: if (firesEventFromNullToModel1) {
241: expectedEventCount++;
242: }
243: assertEquals("Expected event count after null -> model1 ("
244: + null + " -> " + value2 + ").", expectedEventCount,
245: changeReport.eventCount());
246: if (firesEventFromNullToModel1) {
247: eventsOldValue = changeReport.lastOldValue();
248: eventsNewValue = changeReport.lastNewValue();
249: assertEquals(
250: "null-> model1 change fires proper old value.",
251: null, eventsOldValue);
252: assertEquals(
253: "null-> model1 change fires proper new value.",
254: value1, eventsNewValue);
255: }
256:
257: adapter.setBean(model2);
258: boolean firesEventFromModel1ToModel2 = requiresPropertyChangeEvent(
259: value1, value2);
260: if (firesEventFromModel1ToModel2) {
261: expectedEventCount++;
262: }
263: assertEquals("Expected event count after model1 -> model2 ("
264: + value1 + " -> " + value2 + ").", expectedEventCount,
265: changeReport.eventCount());
266: if (firesEventFromModel1ToModel2) {
267: eventsOldValue = changeReport.lastOldValue();
268: eventsNewValue = changeReport.lastNewValue();
269: assertEquals(
270: "model1 -> model2 change fires proper old value.",
271: value1, eventsOldValue);
272: assertEquals(
273: "model1 -> model2 change fires proper new value.",
274: value2, eventsNewValue);
275: }
276:
277: adapter.setBean(null);
278: boolean firesEventFromModel2ToNull = requiresPropertyChangeEvent(
279: value2, null);
280: if (firesEventFromModel2ToNull) {
281: expectedEventCount++;
282: }
283: assertEquals("Expected event count after model2 -> null ("
284: + value2 + " -> " + null + ").", expectedEventCount,
285: changeReport.eventCount());
286: if (firesEventFromModel2ToNull) {
287: eventsOldValue = changeReport.lastOldValue();
288: eventsNewValue = changeReport.lastNewValue();
289: assertEquals(
290: "model2 -> null change fires proper old value.",
291: value2, eventsOldValue);
292: assertEquals(
293: "model2 -> null change fires proper new value.",
294: null, eventsNewValue);
295: }
296: }
297:
298: private void testPropertyAdapterValueChange(Object value1,
299: Object value2) {
300: testValueChange(value1, value2, new PropertyAdapter<TestBean>(
301: model1, "readWriteObjectProperty", true));
302: }
303:
304: private void testBufferedValueModelSubjectChange(Object value1,
305: Object value2) {
306: model1.setReadWriteObjectProperty(value1);
307: model2.setReadWriteObjectProperty(value2);
308:
309: PropertyAdapter<TestBean> adapter1 = new PropertyAdapter<TestBean>(
310: model1, "readWriteObjectProperty", true);
311: PropertyAdapter<TestBean> adapter2 = new PropertyAdapter<TestBean>(
312: model2, "readWriteObjectProperty", true);
313:
314: BufferedValueModel buffer = new BufferedValueModel(null,
315: new Trigger());
316: PropertyChangeReport changeReport = new PropertyChangeReport();
317: buffer.addValueChangeListener(changeReport);
318: Object eventsOldValue;
319: Object eventsNewValue;
320: int expectedEventCount = 0;
321:
322: buffer.setSubject(adapter1);
323: boolean firesEventFromNullToModel1 = requiresPropertyChangeEvent(
324: null, value1);
325: if (firesEventFromNullToModel1) {
326: expectedEventCount++;
327: }
328: assertEquals("Expected event count after null -> adapter1 ("
329: + null + " -> " + value2 + ").", expectedEventCount,
330: changeReport.eventCount());
331: if (firesEventFromNullToModel1) {
332: eventsOldValue = changeReport.lastOldValue();
333: eventsNewValue = changeReport.lastNewValue();
334: assertEquals(
335: "null-> adapter1 change fires proper old value.",
336: null, eventsOldValue);
337: assertEquals(
338: "null-> adapter1 change fires proper new value.",
339: value1, eventsNewValue);
340: }
341:
342: buffer.setSubject(adapter2);
343: boolean firesEventFromModel1ToModel2 = requiresPropertyChangeEvent(
344: value1, value2);
345: if (firesEventFromModel1ToModel2) {
346: expectedEventCount++;
347: }
348: assertEquals(
349: "Expected event count after adapter1 -> adapter2 ("
350: + value1 + " -> " + value2 + ").",
351: expectedEventCount, changeReport.eventCount());
352: if (firesEventFromModel1ToModel2) {
353: eventsOldValue = changeReport.lastOldValue();
354: eventsNewValue = changeReport.lastNewValue();
355: assertEquals(
356: "adapter1 -> adapter2 change fires proper old value.",
357: value1, eventsOldValue);
358: assertEquals(
359: "adapter1 -> adapter2 change fires proper new value.",
360: value2, eventsNewValue);
361: }
362:
363: buffer.setSubject(null);
364: boolean firesEventFromModel2ToNull = requiresPropertyChangeEvent(
365: value2, null);
366: if (firesEventFromModel2ToNull) {
367: expectedEventCount++;
368: }
369: assertEquals("Expected event count after adapter2 -> null ("
370: + value2 + " -> " + null + ").", expectedEventCount,
371: changeReport.eventCount());
372: if (firesEventFromModel2ToNull) {
373: eventsOldValue = changeReport.lastOldValue();
374: eventsNewValue = changeReport.lastNewValue();
375: assertEquals(
376: "adapter2 -> null change fires proper old value.",
377: value2, eventsOldValue);
378: assertEquals(
379: "adapter2 -> null change fires proper new value.",
380: null, eventsNewValue);
381: }
382: }
383:
384: private void testBufferedValueModelSubjectValueChange(
385: Object value1, Object value2) {
386: ValueModel valueModel = new PropertyAdapter<TestBean>(model1,
387: "readWriteObjectProperty", true);
388: ValueModel triggerChannel = new Trigger();
389: testValueChange(value1, value2, new BufferedValueModel(
390: valueModel, triggerChannel));
391: }
392:
393: private void testValueChange(Object value1, Object value2,
394: ValueModel valueModel) {
395: model1.setReadWriteObjectProperty(null);
396: PropertyChangeReport changeReport = new PropertyChangeReport();
397: valueModel.addValueChangeListener(changeReport);
398: Object eventsOldValue;
399: Object eventsNewValue;
400: int expectedEventCount = 0;
401:
402: model1.setReadWriteObjectProperty(value1, true);
403: boolean firesEventFromNullToValue1 = requiresPropertyChangeEventWithNull(
404: null, value1);
405: if (firesEventFromNullToValue1) {
406: expectedEventCount++;
407: }
408: assertEquals("Expected event count after ( null -> " + value2
409: + ").", expectedEventCount, changeReport.eventCount());
410: if (firesEventFromNullToValue1) {
411: eventsOldValue = changeReport.lastOldValue();
412: eventsNewValue = changeReport.lastNewValue();
413: assertEquals(
414: "null-> model1 change fires proper old value.",
415: null, eventsOldValue);
416: assertEquals(
417: "null-> model1 change fires proper new value.",
418: value1, eventsNewValue);
419: }
420:
421: model1.setReadWriteObjectProperty(value2, true);
422: boolean firesEventFromValue1ToValue2 = requiresPropertyChangeEventWithNull(
423: value1, value2);
424: if (firesEventFromValue1ToValue2) {
425: expectedEventCount++;
426: }
427: assertEquals("Expected event count after (" + value1 + " -> "
428: + value2 + ").", expectedEventCount, changeReport
429: .eventCount());
430: if (firesEventFromValue1ToValue2) {
431: eventsOldValue = changeReport.lastOldValue();
432: eventsNewValue = changeReport.lastNewValue();
433: assertEquals(
434: "model1 -> model2 change fires proper old value.",
435: value1, eventsOldValue);
436: assertEquals(
437: "model1 -> model2 change fires proper new value.",
438: value2, eventsNewValue);
439: }
440:
441: model1.setReadWriteObjectProperty(null, true);
442: boolean firesEventFromValue2ToNull = requiresPropertyChangeEventWithNull(
443: value2, null);
444: if (firesEventFromValue2ToNull) {
445: expectedEventCount++;
446: }
447: assertEquals("Expected event count after (" + value2 + " -> "
448: + null + ").", expectedEventCount, changeReport
449: .eventCount());
450: if (firesEventFromValue2ToNull) {
451: eventsOldValue = changeReport.lastOldValue();
452: eventsNewValue = changeReport.lastNewValue();
453: assertEquals(
454: "model2 -> null change fires proper old value.",
455: value2, eventsOldValue);
456: assertEquals(
457: "model2 -> null change fires proper new value.",
458: null, eventsNewValue);
459: }
460: }
461:
462: // Helper Code ************************************************************
463:
464: private Object[][] createOldAndNewValuePairs() {
465: String sameValue = "same value";
466: List<String> list1a = Collections.emptyList();
467: List<String> list1b = new LinkedList<String>();
468: List<String> list2a = new ArrayList<String>();
469: list2a.add("one");
470: List<String> list2b = new ArrayList<String>(list2a);
471: List<String> list3 = new ArrayList<String>(list2a);
472: list3.add("two");
473: return new Object[][] { { null, null }, { null, "value" },
474: { "value", null }, { sameValue, sameValue },
475: { "equal value", new String("equal value") },
476: { "value1", "value2" }, { new Float(1), new Float(1) },
477: { new Float(1), new Float(2) },
478: { Boolean.TRUE, new Boolean(true) },
479: { list1a, list1a }, { list1a, list1b },
480: { list1a, list2a }, { list2a, list2a },
481: { list2a, list2b }, { list2a, list3 }, };
482: }
483:
484: /**
485: * Checks and answers whether changing a property from value1 to value2
486: * requires to send a PropertyChangeEvent. A future version may be
487: * placed in class Model or ExtendedPropertyChangeSupport; it may test
488: * for known core types that can be compared via #equals, not ==.
489: */
490: private boolean requiresPropertyChangeEvent(Object value1,
491: Object value2) {
492: return value1 != value2;
493: }
494:
495: /**
496: * Checks and answers whether changing a property from value1 to value2
497: * requires to send a PropertyChangeEvent. A future version may be
498: * placed in class Model or ExtendedPropertyChangeSupport; it may test
499: * for known core types that can be compared via #equals, not ==.
500: */
501: private boolean requiresPropertyChangeEventWithNull(Object value1,
502: Object value2) {
503: return (value1 != value2) || (value1 == null && value2 == null);
504: }
505:
506: }
|