001: // Copyright 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.internal.services;
016:
017: import java.util.Arrays;
018: import java.util.Collections;
019:
020: import org.apache.tapestry.ComponentResources;
021: import org.apache.tapestry.PropertyConduit;
022: import org.apache.tapestry.beaneditor.BeanModel;
023: import org.apache.tapestry.beaneditor.PropertyModel;
024: import org.apache.tapestry.internal.test.InternalBaseTestCase;
025: import org.apache.tapestry.ioc.Messages;
026: import org.apache.tapestry.services.BeanModelSource;
027: import org.testng.annotations.AfterClass;
028: import org.testng.annotations.BeforeClass;
029: import org.testng.annotations.Test;
030:
031: /** Tests for the bean editor model source itself, as well as the model classes. */
032: public class BeanModelSourceImplTest extends InternalBaseTestCase {
033: private BeanModelSource _source;
034:
035: @BeforeClass
036: public void setup() {
037: _source = getObject(BeanModelSource.class, null);
038: }
039:
040: @AfterClass
041: public void cleanup() {
042: _source = null;
043: }
044:
045: /** Tests defaults for property names, labels and conduits. */
046: @Test
047: public void default_model_for_bean() {
048: ComponentResources resources = mockComponentResources();
049: Messages messages = mockMessages();
050:
051: train_getMessages(resources, messages);
052: stub_contains(messages, false);
053:
054: replay();
055:
056: BeanModel model = _source.create(SimpleBean.class, true,
057: resources);
058:
059: assertSame(model.getBeanType(), SimpleBean.class);
060:
061: // Based on order of the getter methods (no longer alphabetical)
062:
063: assertEquals(model.getPropertyNames(), Arrays.asList(
064: "firstName", "lastName", "age"));
065:
066: PropertyModel age = model.get("age");
067:
068: assertEquals(age.getLabel(), "Age");
069: assertSame(age.getPropertyType(), int.class);
070: assertEquals(age.getDataType(), "text");
071:
072: PropertyModel firstName = model.get("firstName");
073:
074: assertEquals(firstName.getLabel(), "First Name");
075: assertEquals(firstName.getPropertyType(), String.class);
076: assertEquals(firstName.getDataType(), "text");
077:
078: assertEquals(model.get("lastName").getLabel(), "Last Name");
079:
080: PropertyConduit conduit = model.get("lastName").getConduit();
081:
082: SimpleBean instance = new SimpleBean();
083:
084: instance.setLastName("Lewis Ship");
085:
086: assertEquals(conduit.get(instance), "Lewis Ship");
087:
088: conduit.set(instance, "TapestryDude");
089:
090: assertEquals(instance.getLastName(), "TapestryDude");
091:
092: // Now, one with some type coercion.
093:
094: age.getConduit().set(instance, "40");
095:
096: assertEquals(instance.getAge(), 40);
097:
098: verify();
099: }
100:
101: @Test
102: public void filtering_out_read_only_properties() {
103: ComponentResources resources = mockComponentResources();
104: Messages messages = mockMessages();
105:
106: train_getMessages(resources, messages);
107: stub_contains(messages, false);
108:
109: replay();
110:
111: BeanModel model = _source.create(ReadOnlyBean.class, true,
112: resources);
113:
114: assertEquals(model.getPropertyNames(), Arrays.asList("value"));
115:
116: model = _source.create(ReadOnlyBean.class, false, resources);
117:
118: assertEquals(model.getPropertyNames(), Arrays.asList("value",
119: "readOnly"));
120:
121: verify();
122: }
123:
124: @Test
125: public void non_text_property() {
126: ComponentResources resources = mockComponentResources();
127: Messages messages = mockMessages();
128:
129: train_getMessages(resources, messages);
130: stub_contains(messages, false);
131:
132: replay();
133:
134: BeanModel model = _source.create(EnumBean.class, true,
135: resources);
136:
137: assertEquals(model.getPropertyNames(), Arrays.asList("token"));
138:
139: assertEquals(model.get("token").getDataType(), "enum");
140:
141: verify();
142: }
143:
144: @Test
145: public void add_duplicate_property_name_is_failure() {
146: ComponentResources resources = mockComponentResources();
147: Messages messages = mockMessages();
148:
149: train_getMessages(resources, messages);
150: stub_contains(messages, false);
151:
152: replay();
153:
154: BeanModel model = _source.create(SimpleBean.class, true,
155: resources);
156:
157: try {
158: model.add("age");
159: unreachable();
160: } catch (RuntimeException ex) {
161: assertEquals(
162: ex.getMessage(),
163: "Bean editor model for org.apache.tapestry.internal.services.SimpleBean already contains a property model for property \'age\'.");
164: }
165:
166: verify();
167: }
168:
169: @Test
170: public void unknown_property_name() {
171: ComponentResources resources = mockComponentResources();
172: Messages messages = mockMessages();
173:
174: train_getMessages(resources, messages);
175: stub_contains(messages, false);
176:
177: replay();
178:
179: BeanModel model = _source.create(SimpleBean.class, true,
180: resources);
181:
182: try {
183: model.get("frobozz");
184: unreachable();
185: } catch (RuntimeException ex) {
186: assertEquals(
187: ex.getMessage(),
188: "Bean editor model for org.apache.tapestry.internal.services.SimpleBean does not contain a property named \'frobozz\'. "
189: + "Available properties: age, firstName, lastName.");
190: }
191:
192: verify();
193: }
194:
195: @Test
196: public void order_via_annotation() {
197: ComponentResources resources = mockComponentResources();
198: Messages messages = mockMessages();
199:
200: train_getMessages(resources, messages);
201: stub_contains(messages, false);
202:
203: replay();
204:
205: BeanModel model = _source.create(StoogeBean.class, true,
206: resources);
207:
208: assertEquals(model.getPropertyNames(), Arrays.asList("larry",
209: "moe", "shemp", "curly"));
210:
211: verify();
212: }
213:
214: @Test
215: public void edit_property_label() {
216: ComponentResources resources = mockComponentResources();
217: Messages messages = mockMessages();
218:
219: train_getMessages(resources, messages);
220: stub_contains(messages, false);
221:
222: replay();
223:
224: BeanModel model = _source.create(SimpleBean.class, true,
225: resources).get("age").label("Decrepitude").model();
226:
227: assertEquals(model.get("age").getLabel(), "Decrepitude");
228:
229: verify();
230: }
231:
232: @Test
233: public void label_from_component_messages() {
234: ComponentResources resources = mockComponentResources();
235: Messages messages = mockMessages();
236:
237: train_getMessages(resources, messages);
238: stub_contains(messages, false);
239:
240: train_contains(messages, "age-label", true);
241: train_get(messages, "age-label", "Decrepitude");
242:
243: replay();
244:
245: BeanModel model = _source.create(SimpleBean.class, true,
246: resources);
247:
248: assertEquals(model.get("age").getLabel(), "Decrepitude");
249:
250: verify();
251: }
252:
253: @Test
254: public void array_type_bean() {
255: ComponentResources resources = mockComponentResources();
256: Messages messages = mockMessages();
257:
258: train_getMessages(resources, messages);
259: stub_contains(messages, false);
260:
261: replay();
262:
263: BeanModel model = _source.create(StringArrayBean.class, true,
264: resources);
265:
266: // There's not editor for string arrays yet, so it won't show up normally.
267:
268: PropertyModel propertyModel = model.add("array");
269:
270: assertSame(propertyModel.getPropertyType(), String[].class);
271:
272: String[] value = { "foo", "bar" };
273:
274: StringArrayBean bean = new StringArrayBean();
275:
276: PropertyConduit conduit = propertyModel.getConduit();
277:
278: conduit.set(bean, value);
279:
280: assertSame(bean.getArray(), value);
281:
282: assertSame(conduit.get(bean), value);
283:
284: verify();
285: }
286:
287: @Test
288: public void composite_bean() {
289: ComponentResources resources = mockComponentResources();
290: Messages messages = mockMessages();
291:
292: train_getMessages(resources, messages);
293: stub_contains(messages, false);
294:
295: train_contains(messages, "simpleage-label", true);
296: train_get(messages, "simpleage-label", "Years of Age");
297:
298: replay();
299:
300: BeanModel model = _source.create(CompositeBean.class, true,
301: resources);
302:
303: // No editor for CompositeBean, so this will be empty.
304:
305: assertEquals(model.getPropertyNames(), Collections.emptyList());
306:
307: // There's not editor for string arrays yet, so it won't show up normally.
308:
309: PropertyModel firstName = model.add("simple.firstName");
310:
311: assertEquals(firstName.getLabel(), "First Name");
312:
313: PropertyModel age = model.add("simple.age");
314: assertEquals(age.getLabel(), "Years of Age");
315:
316: CompositeBean bean = new CompositeBean();
317:
318: firstName.getConduit().set(bean, "Fred");
319: age.getConduit().set(bean, "97");
320:
321: assertEquals(bean.getSimple().getFirstName(), "Fred");
322: assertEquals(bean.getSimple().getAge(), 97);
323:
324: bean.getSimple().setAge(24);
325:
326: assertEquals(age.getConduit().get(bean), new Integer(24));
327:
328: verify();
329: }
330:
331: @Test
332: public void default_properties_exclude_write_only() {
333: ComponentResources resources = mockComponentResources();
334: Messages messages = mockMessages();
335:
336: train_getMessages(resources, messages);
337: stub_contains(messages, false);
338:
339: replay();
340:
341: BeanModel model = _source.create(WriteOnlyBean.class, false,
342: resources);
343:
344: assertEquals(model.getPropertyNames(), Arrays.asList(
345: "readOnly", "readWrite"));
346:
347: verify();
348: }
349:
350: @Test
351: public void add_synthetic_property() {
352: ComponentResources resources = mockComponentResources();
353: Messages messages = mockMessages();
354:
355: train_getMessages(resources, messages);
356: stub_contains(messages, false);
357:
358: replay();
359:
360: BeanModel model = _source.create(SimpleBean.class, true,
361: resources);
362:
363: PropertyModel property = model.add("placeholder", null);
364:
365: assertFalse(property.isSortable());
366: assertSame(property.getPropertyType(), Object.class);
367: assertEquals(property.getLabel(), "Placeholder");
368: assertEquals(property.getOrder(), 0);
369:
370: verify();
371: }
372:
373: @Test
374: public void remove_property() {
375: ComponentResources resources = mockComponentResources();
376: Messages messages = mockMessages();
377:
378: train_getMessages(resources, messages);
379: stub_contains(messages, false);
380:
381: replay();
382:
383: BeanModel model = _source.create(SimpleBean.class, true,
384: resources);
385:
386: assertSame(model.remove("age"), model);
387:
388: assertEquals(model.getPropertyNames(), Arrays.asList(
389: "firstName", "lastName"));
390:
391: verify();
392: }
393:
394: @Test
395: public void remove_unknown_property_is_noop() {
396: ComponentResources resources = mockComponentResources();
397: Messages messages = mockMessages();
398:
399: train_getMessages(resources, messages);
400: stub_contains(messages, false);
401:
402: replay();
403:
404: BeanModel model = _source.create(SimpleBean.class, true,
405: resources);
406:
407: assertSame(model.remove("frobozz"), model);
408:
409: assertEquals(model.getPropertyNames(), Arrays.asList(
410: "firstName", "lastName", "age"));
411:
412: verify();
413: }
414:
415: @Test
416: public void nonvisual_properties_are_excluded() {
417: ComponentResources resources = mockComponentResources();
418: Messages messages = mockMessages();
419:
420: train_getMessages(resources, messages);
421: stub_contains(messages, false);
422:
423: replay();
424:
425: BeanModel model = _source.create(NonVisualBean.class, true,
426: resources);
427:
428: assertEquals(model.getPropertyNames(), Arrays.asList("name"));
429:
430: verify();
431: }
432: }
|