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.PropertyVetoException;
034:
035: import junit.framework.TestCase;
036:
037: import com.jgoodies.binding.PresentationModel;
038: import com.jgoodies.binding.tests.beans.EquityTestBean;
039: import com.jgoodies.binding.tests.beans.TestBean;
040: import com.jgoodies.binding.tests.event.PropertyChangeReport;
041: import com.jgoodies.binding.value.BufferedValueModel;
042: import com.jgoodies.binding.value.Trigger;
043: import com.jgoodies.binding.value.ValueHolder;
044:
045: /**
046: * A test case for class {@link com.jgoodies.binding.PresentationModel}.
047: *
048: * @author Karsten Lentzsch
049: * @version $Revision: 1.10 $
050: */
051: public final class PresentationModelTest extends TestCase {
052:
053: // Null As Property Name **************************************************
054:
055: public void testRejectNullPropertyName() {
056: testRejectNullPropertyName(null);
057: testRejectNullPropertyName(new TestBean());
058: }
059:
060: private void testRejectNullPropertyName(TestBean bean) {
061: PresentationModel<TestBean> model = new PresentationModel<TestBean>(
062: bean);
063: try {
064: model.getValue(null);
065: fail("#getValue(null) should throw an NPE.");
066: } catch (NullPointerException e) {
067: // The expected behavior
068: }
069: try {
070: model.setValue(null, null);
071: fail("#setValue(null, Object) should throw an NPE.");
072: } catch (NullPointerException e) {
073: // The expected behavior
074: }
075: try {
076: model.setVetoableValue(null, null);
077: fail("#setVetoableValue(null, Object) should throw an NPE.");
078: } catch (NullPointerException e) {
079: // The expected behavior
080: } catch (PropertyVetoException e) {
081: fail("An NPE should be thrown.");
082: }
083: try {
084: model.getBufferedValue(null);
085: fail("#getBufferedValue(null) should throw an NPE.");
086: } catch (NullPointerException e) {
087: // The expected behavior
088: }
089: try {
090: model.setBufferedValue(null, null);
091: fail("#setBufferedValue(null, Object) should throw an NPE.");
092: } catch (NullPointerException e) {
093: // The expected behavior
094: }
095: try {
096: model.getModel(null);
097: fail("#getModel(null) should throw an NPE.");
098: } catch (NullPointerException e) {
099: // The expected behavior
100: }
101: try {
102: model.getModel(null, "readA", "writeA");
103: fail("#getModel(null, String, String) should throw an NPE.");
104: } catch (NullPointerException e) {
105: // The expected behavior
106: }
107: try {
108: model.getComponentModel(null);
109: fail("#getComponentModel(null) should throw an NPE.");
110: } catch (NullPointerException e) {
111: // The expected behavior
112: }
113: try {
114: model.getBufferedModel(null);
115: fail("#getBufferedModel(null) should throw an NPE.");
116: } catch (NullPointerException e) {
117: // The expected behavior
118: }
119: try {
120: model.getBufferedModel(null, "readA", "writeA");
121: fail("#getBufferedModel(null, String, String) should throw an NPE.");
122: } catch (NullPointerException e) {
123: // The expected behavior
124: }
125: try {
126: model.getBufferedComponentModel(null);
127: fail("#getBufferedComponentModel(null) should throw an NPE.");
128: } catch (NullPointerException e) {
129: // The expected behavior
130: }
131: }
132:
133: // ************************************************************************
134:
135: /**
136: * Verifies that the factory method vends the same instance of the
137: * buffered model if called multiple times.
138: */
139: public void testVendsSameModel() {
140: PresentationModel<TestBean> model = new PresentationModel<TestBean>(
141: new TestBean());
142: Object model1 = model.getModel("readWriteObjectProperty");
143: Object model2 = model.getModel("readWriteObjectProperty");
144:
145: assertSame("The factory method vends the same instance.",
146: model1, model2);
147: }
148:
149: /**
150: * Verifies that the factory method vends the same instance of the
151: * buffered model if called multiple times.
152: */
153: public void testVendsSameBufferedModel() {
154: PresentationModel<TestBean> model = new PresentationModel<TestBean>(
155: new TestBean());
156: Object model1 = model
157: .getBufferedModel("readWriteObjectProperty");
158: Object model2 = model
159: .getBufferedModel("readWriteObjectProperty");
160:
161: assertSame("The factory method vends the same instance.",
162: model1, model2);
163: }
164:
165: /**
166: * Verifies that the PresentationModel rejects attempts to get an adapting
167: * ValueModel by means of <code>#getModel</code> with different
168: * property accessor names. In other words, for each bean property
169: * API users must use either {@link PresentationModel#getModel(String)} or
170: * {@link PresentationModel#getModel(String, String, String)}, not both.
171: * And all calls to the latter method must use the same getter and setter
172: * names for the same property name.<p>
173: *
174: * This test invokes both methods for the same property name with different
175: * getter and/or setter names and expects that the second call is rejected.
176: * The PresentationModel is created without a bean set, to avoid that the
177: * underlying BeanAdapter checks for a valid property.
178: */
179: public void testRejectsGetModelWithDifferentAccessors() {
180: String failureText = "The PresentationModel must reject attempts "
181: + "to get a ValueModel for the same property "
182: + "with different accessor names.";
183: String propertyName = "property";
184: String getterName1 = "getter1";
185: String getterName2 = "getter2";
186: String setterName1 = "setter1";
187: String setterName2 = "setter2";
188:
189: PresentationModel<Object> model1 = new PresentationModel<Object>(
190: null);
191: model1.getModel(propertyName);
192: try {
193: model1.getModel(propertyName, getterName1, setterName1);
194: fail(failureText);
195: } catch (IllegalArgumentException e) {
196: // The expected result.
197: }
198:
199: PresentationModel<Object> model2 = new PresentationModel<Object>(
200: null);
201: model2.getModel(propertyName, getterName1, setterName1);
202: try {
203: model2.getModel(propertyName);
204: fail(failureText);
205: } catch (IllegalArgumentException e) {
206: // The expected result.
207: }
208:
209: PresentationModel<Object> model3 = new PresentationModel<Object>(
210: null);
211: model3.getModel(propertyName, getterName1, setterName1);
212: try {
213: model3.getModel(propertyName, getterName2, setterName1);
214: fail(failureText);
215: } catch (IllegalArgumentException e) {
216: // The expected result.
217: }
218:
219: PresentationModel<Object> model4 = new PresentationModel<Object>(
220: null);
221: model4.getModel(propertyName, getterName1, setterName1);
222: try {
223: model4.getModel(propertyName, getterName1, setterName2);
224: fail(failureText);
225: } catch (IllegalArgumentException e) {
226: // The expected result.
227: }
228: }
229:
230: /**
231: * Verifies that the PresentationModel rejects attempts to get a buffered
232: * adapting ValueModel by means of <code>#getBufferedModel</code> with
233: * different accessor names. In other words, for each bean property API
234: * users must use either {@link PresentationModel#getBufferedModel(String)}
235: * or {@link PresentationModel#getBufferedModel(String, String, String)},
236: * not both. And all calls to the latter method must use the same getter
237: * and setter names for the same property name.<p>
238: *
239: * This test invokes both methods for the same property name with different
240: * getter and/or setter names and expects that the second call is rejected.
241: * The PresentationModel is created without a bean set, to avoid that the
242: * underlying BeanAdapter checks for a valid property.
243: */
244: public void testRejectsGetBufferedModelWithDifferentAccessors() {
245: String failureText = "The PresentationModel must reject attempts "
246: + "to get a buffered ValueModel for the same property "
247: + "with different accessor names.";
248: String propertyName = "property";
249: String getterName1 = "getter1";
250: String getterName2 = "getter2";
251: String setterName1 = "setter1";
252: String setterName2 = "setter2";
253:
254: PresentationModel<Object> model1 = new PresentationModel<Object>(
255: null);
256: model1.getBufferedModel(propertyName);
257: try {
258: model1.getBufferedModel(propertyName, getterName1,
259: setterName1);
260: fail(failureText);
261: } catch (IllegalArgumentException e) {
262: // The expected result.
263: }
264:
265: PresentationModel<Object> model2 = new PresentationModel<Object>(
266: null);
267: model2.getBufferedModel(propertyName, getterName1, setterName1);
268: try {
269: model2.getBufferedModel(propertyName);
270: fail(failureText);
271: } catch (IllegalArgumentException e) {
272: // The expected result.
273: }
274:
275: PresentationModel<Object> model3 = new PresentationModel<Object>(
276: null);
277: model3.getBufferedModel(propertyName, getterName1, setterName1);
278: try {
279: model3.getBufferedModel(propertyName, getterName2,
280: setterName1);
281: fail(failureText);
282: } catch (IllegalArgumentException e) {
283: // The expected result.
284: }
285:
286: PresentationModel<Object> model4 = new PresentationModel<Object>(
287: null);
288: model4.getBufferedModel(propertyName, getterName1, setterName1);
289: try {
290: model4.getBufferedModel(propertyName, getterName1,
291: setterName2);
292: fail(failureText);
293: } catch (IllegalArgumentException e) {
294: // The expected result.
295: }
296: }
297:
298: public void testSetTriggerChannelUpdatesExistingBufferedValueModels() {
299: Object value1 = "value1";
300: Object value2 = "value2";
301: Object value3 = "value3";
302: Object value4 = "value4";
303: TestBean bean = new TestBean();
304: bean.setReadWriteObjectProperty(value1);
305:
306: Trigger trigger1 = new Trigger();
307: Trigger trigger2 = new Trigger();
308: PresentationModel<TestBean> model = new PresentationModel<TestBean>(
309: bean, trigger1);
310: BufferedValueModel buffer = model
311: .getBufferedModel("readWriteObjectProperty");
312: buffer.setValue(value2);
313:
314: trigger1.triggerCommit();
315: assertEquals(
316: "Before the trigger change Trigger1 commits buffered values.",
317: value2, bean.getReadWriteObjectProperty());
318:
319: buffer.setValue(value3);
320: trigger2.triggerCommit();
321: assertEquals(
322: "Before the trigger change Trigger2 does not affect the buffer.",
323: value2, bean.getReadWriteObjectProperty());
324:
325: model.setTriggerChannel(trigger2);
326: trigger1.triggerCommit();
327: assertEquals(
328: "After the trigger change Trigger1 shall not affect the buffered value anymore.",
329: value2, bean.getReadWriteObjectProperty());
330:
331: buffer.setValue(value4);
332: trigger2.triggerCommit();
333: assertEquals(
334: "After the trigger change Trigger2 shall commit buffered values.",
335: value4, bean.getReadWriteObjectProperty());
336: }
337:
338: // Testing Bean Changes ***************************************************
339:
340: public void testBeanChangeFiresThreeBeanEvents() {
341: TestBean bean = new TestBean();
342: PresentationModel<TestBean> model = new PresentationModel<TestBean>(
343: null);
344: PropertyChangeReport changeReport = new PropertyChangeReport();
345: model.addPropertyChangeListener(changeReport);
346:
347: model.setBean(bean);
348: assertEquals(
349: "Changing the bean fires three events: before, changing, after.",
350: 3, changeReport.eventCount());
351: }
352:
353: public void testEqualBeanChangeFiresThreeBeanEvents() {
354: EquityTestBean bean1 = new EquityTestBean("bean");
355: EquityTestBean bean2 = new EquityTestBean("bean");
356: assertEquals("The two test beans are equal.", bean1, bean2);
357: assertNotSame("The two test beans are not the same.", bean1,
358: bean2);
359:
360: PresentationModel<EquityTestBean> model1 = new PresentationModel<EquityTestBean>(
361: bean1);
362: PropertyChangeReport beanChannelValueChangeReport = new PropertyChangeReport();
363: model1.getBeanChannel().addValueChangeListener(
364: beanChannelValueChangeReport);
365: PropertyChangeReport changeReport1 = new PropertyChangeReport();
366: model1.addPropertyChangeListener(changeReport1);
367:
368: model1.setBean(bean2);
369: assertEquals(
370: "Changing the bean fires a change event in the bean channel.",
371: 1, beanChannelValueChangeReport.eventCount());
372: assertEquals(
373: "Changing the bean fires three events: before, changing, after.",
374: 3, changeReport1.eventCount());
375:
376: PresentationModel<EquityTestBean> model2 = new PresentationModel<EquityTestBean>(
377: new ValueHolder(null, true));
378: model2.setBean(bean1);
379: PropertyChangeReport changeReport2 = new PropertyChangeReport();
380: model2.addPropertyChangeListener(changeReport2);
381:
382: model2.setBean(bean2);
383: assertEquals(
384: "Changing the bean fires three events: before, changing, after.",
385: 3, changeReport2.eventCount());
386: }
387:
388: }
|