Java tutorial
/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sf.juffrou.reflect.spring; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.beans.PropertyEditorSupport; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import net.sf.juffrou.reflect.JuffrouSpringBeanWrapper; import org.apache.commons.logging.LogFactory; import org.junit.Test; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.NotReadablePropertyException; import org.springframework.beans.NotWritablePropertyException; import org.springframework.beans.NullValueInNestedPathException; import org.springframework.beans.PropertyAccessException; import org.springframework.beans.PropertyBatchUpdateException; import org.springframework.beans.PropertyValue; import org.springframework.beans.TypeMismatchException; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.propertyeditors.CustomNumberEditor; import org.springframework.beans.propertyeditors.StringArrayPropertyEditor; import org.springframework.beans.propertyeditors.StringTrimmerEditor; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.util.StopWatch; import org.springframework.util.StringUtils; import test.beans.BooleanTestBean; import test.beans.ITestBean; import test.beans.IndexedTestBean; import test.beans.NumberTestBean; import test.beans.TestBean; /** * @author Rod Johnson * @author Juergen Hoeller * @author Alef Arendsen * @author Arjen Poutsma * @author Chris Beams * @author Dave Syer */ public final class BeanWrapperTests { @Test public void testNullNestedTypeDescriptor() { Foo foo = new Foo(); JuffrouSpringBeanWrapper wrapper = new JuffrouSpringBeanWrapper(foo); wrapper.setConversionService(new DefaultConversionService()); wrapper.setAutoGrowNestedPaths(true); wrapper.setPropertyValue("listOfMaps[0]['luckyNumber']", "9"); assertEquals("9", foo.listOfMaps.get(0).get("luckyNumber")); } @Test public void testNullNestedTypeDescriptor2() { Foo foo = new Foo(); JuffrouSpringBeanWrapper wrapper = new JuffrouSpringBeanWrapper(foo); wrapper.setConversionService(new DefaultConversionService()); wrapper.setAutoGrowNestedPaths(true); Map<String, String> map = new HashMap<String, String>(); map.put("favoriteNumber", "9"); wrapper.setPropertyValue("list[0]", map); assertEquals(map, foo.list.get(0)); } @Test public void testNullNestedTypeDescriptorWithNoConversionService() { Foo foo = new Foo(); JuffrouSpringBeanWrapper wrapper = new JuffrouSpringBeanWrapper(foo); wrapper.setAutoGrowNestedPaths(true); wrapper.setPropertyValue("listOfMaps[0]['luckyNumber']", "9"); assertEquals("9", foo.listOfMaps.get(0).get("luckyNumber")); } @Test public void testNullNestedTypeDescriptorWithBadConversionService() { Foo foo = new Foo(); JuffrouSpringBeanWrapper wrapper = new JuffrouSpringBeanWrapper(foo); wrapper.setConversionService(new GenericConversionService() { @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { throw new ConversionFailedException(sourceType, targetType, source, null); } }); wrapper.setAutoGrowNestedPaths(true); wrapper.setPropertyValue("listOfMaps[0]['luckyNumber']", "9"); assertEquals("9", foo.listOfMaps.get(0).get("luckyNumber")); } @Test public void testIsReadablePropertyNotReadable() { NoRead nr = new NoRead(); BeanWrapper bw = new JuffrouSpringBeanWrapper(nr); assertFalse(bw.isReadableProperty("age")); } /** * Shouldn't throw an exception: should just return false */ @Test public void testIsReadablePropertyNoSuchProperty() { NoRead nr = new NoRead(); BeanWrapper bw = new JuffrouSpringBeanWrapper(nr); assertFalse(bw.isReadableProperty("xxxxx")); } @Test public void testIsReadablePropertyNull() { NoRead nr = new NoRead(); BeanWrapper bw = new JuffrouSpringBeanWrapper(nr); try { bw.isReadableProperty(null); fail("Can't inquire into readability of null property"); } catch (IllegalArgumentException ex) { // expected } } @Test public void testIsWritablePropertyNull() { NoRead nr = new NoRead(); BeanWrapper bw = new JuffrouSpringBeanWrapper(nr); try { bw.isWritableProperty(null); fail("Can't inquire into writability of null property"); } catch (IllegalArgumentException ex) { // expected } } @Test public void testReadableAndWritableForIndexedProperties() { BeanWrapper bw = new JuffrouSpringBeanWrapper(IndexedTestBean.class); assertTrue(bw.isReadableProperty("array")); assertTrue(bw.isReadableProperty("list")); assertTrue(bw.isReadableProperty("set")); assertTrue(bw.isReadableProperty("map")); assertFalse(bw.isReadableProperty("xxx")); assertTrue(bw.isWritableProperty("array")); assertTrue(bw.isWritableProperty("list")); assertTrue(bw.isWritableProperty("set")); assertTrue(bw.isWritableProperty("map")); assertFalse(bw.isWritableProperty("xxx")); assertTrue(bw.isReadableProperty("array[0]")); assertTrue(bw.isReadableProperty("array[0].name")); assertTrue(bw.isReadableProperty("list[0]")); assertTrue(bw.isReadableProperty("list[0].name")); assertTrue(bw.isReadableProperty("set[0]")); assertTrue(bw.isReadableProperty("set[0].name")); assertTrue(bw.isReadableProperty("map[key1]")); assertTrue(bw.isReadableProperty("map[key1].name")); assertTrue(bw.isReadableProperty("map[key4][0]")); assertTrue(bw.isReadableProperty("map[key4][0].name")); assertTrue(bw.isReadableProperty("map[key4][1]")); assertTrue(bw.isReadableProperty("map[key4][1].name")); assertFalse(bw.isReadableProperty("array[key1]")); assertTrue(bw.isWritableProperty("array[0]")); assertTrue(bw.isWritableProperty("array[0].name")); assertTrue(bw.isWritableProperty("list[0]")); assertTrue(bw.isWritableProperty("list[0].name")); assertTrue(bw.isWritableProperty("set[0]")); assertTrue(bw.isWritableProperty("set[0].name")); assertTrue(bw.isWritableProperty("map[key1]")); assertTrue(bw.isWritableProperty("map[key1].name")); assertTrue(bw.isWritableProperty("map[key4][0]")); assertTrue(bw.isWritableProperty("map[key4][0].name")); assertTrue(bw.isWritableProperty("map[key4][1]")); assertTrue(bw.isWritableProperty("map[key4][1].name")); assertFalse(bw.isWritableProperty("array[key1]")); } @Test public void testTypeDeterminationForIndexedProperty() { BeanWrapper bw = new JuffrouSpringBeanWrapper(IndexedTestBean.class); assertEquals(null, bw.getPropertyType("map[key0]")); bw = new JuffrouSpringBeanWrapper(IndexedTestBean.class); bw.setPropertyValue("map[key0]", "my String"); assertEquals(String.class, bw.getPropertyType("map[key0]")); bw = new JuffrouSpringBeanWrapper(IndexedTestBean.class); bw.registerCustomEditor(String.class, "map[key0]", new StringTrimmerEditor(false)); assertEquals(String.class, bw.getPropertyType("map[key0]")); } @Test public void testGetterThrowsException() { GetterBean gb = new GetterBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(gb); bw.setPropertyValue("name", "tom"); assertTrue("Set name to tom", gb.getName().equals("tom")); } @Test public void testEmptyPropertyValuesSet() { TestBean t = new TestBean(); int age = 50; String name = "Tony"; t.setAge(age); t.setName(name); try { BeanWrapper bw = new JuffrouSpringBeanWrapper(t); assertTrue("age is OK", t.getAge() == age); assertTrue("name is OK", name.equals(t.getName())); bw.setPropertyValues(new MutablePropertyValues()); // Check its unchanged assertTrue("age is OK", t.getAge() == age); assertTrue("name is OK", name.equals(t.getName())); } catch (BeansException ex) { fail("Shouldn't throw exception when everything is valid"); } } @Test public void testAllValid() { TestBean t = new TestBean(); String newName = "tony"; int newAge = 65; String newTouchy = "valid"; try { BeanWrapper bw = new JuffrouSpringBeanWrapper(t); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValue(new PropertyValue("age", new Integer(newAge))); pvs.addPropertyValue(new PropertyValue("name", newName)); pvs.addPropertyValue(new PropertyValue("touchy", newTouchy)); bw.setPropertyValues(pvs); assertTrue("Validly set property must stick", t.getName().equals(newName)); assertTrue("Validly set property must stick", t.getTouchy().equals(newTouchy)); assertTrue("Validly set property must stick", t.getAge() == newAge); } catch (BeansException ex) { fail("Shouldn't throw exception when everything is valid"); } } @Test public void testBeanWrapperUpdates() { TestBean t = new TestBean(); int newAge = 33; try { BeanWrapper bw = new JuffrouSpringBeanWrapper(t); t.setAge(newAge); Object bwAge = bw.getPropertyValue("age"); assertTrue("Age is an integer", bwAge instanceof Integer); int bwi = ((Integer) bwAge).intValue(); assertTrue("Bean wrapper must pick up changes", bwi == newAge); } catch (Exception ex) { fail("Shouldn't throw exception when everything is valid"); } } @Test public void testValidNullUpdate() { TestBean t = new TestBean(); t.setName("Frank"); // we need to change it back t.setSpouse(t); BeanWrapper bw = new JuffrouSpringBeanWrapper(t); assertTrue("name is not null to start off", t.getName() != null); bw.setPropertyValue("name", null); assertTrue("name is now null", t.getName() == null); // now test with non-string assertTrue("spouse is not null to start off", t.getSpouse() != null); bw.setPropertyValue("spouse", null); assertTrue("spouse is now null", t.getSpouse() == null); } @Test public void testIgnoringIndexedProperty() { MutablePropertyValues values = new MutablePropertyValues(); values.add("toBeIgnored[0]", new Integer(42)); BeanWrapper bw = new JuffrouSpringBeanWrapper(new Object()); bw.setPropertyValues(values, true); } @Test public void testConvertPrimitiveToString() { MutablePropertyValues values = new MutablePropertyValues(); values.add("name", new Integer(42)); TestBean tb = new TestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.setPropertyValues(values); assertEquals("42", tb.getName()); } @Test public void testConvertClassToString() { MutablePropertyValues values = new MutablePropertyValues(); values.add("name", Integer.class); TestBean tb = new TestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.registerCustomEditor(String.class, new PropertyEditorSupport() { @Override public void setValue(Object value) { super.setValue(value.toString()); } }); bw.setPropertyValues(values); assertEquals(Integer.class.toString(), tb.getName()); } @Test public void testBooleanObject() { BooleanTestBean tb = new BooleanTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.setPropertyValue("bool2", "true"); assertTrue("Correct bool2 value", Boolean.TRUE.equals(bw.getPropertyValue("bool2"))); assertTrue("Correct bool2 value", tb.getBool2().booleanValue()); bw.setPropertyValue("bool2", "false"); assertTrue("Correct bool2 value", Boolean.FALSE.equals(bw.getPropertyValue("bool2"))); assertTrue("Correct bool2 value", !tb.getBool2().booleanValue()); } @Test public void testNumberObjects() { NumberTestBean tb = new NumberTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); try { bw.setPropertyValue("short2", "2"); bw.setPropertyValue("int2", "8"); bw.setPropertyValue("long2", "6"); bw.setPropertyValue("bigInteger", "3"); bw.setPropertyValue("float2", "8.1"); bw.setPropertyValue("double2", "6.1"); bw.setPropertyValue("bigDecimal", "4.0"); } catch (BeansException ex) { fail("Should not throw BeansException: " + ex.getMessage()); } assertTrue("Correct short2 value", new Short("2").equals(bw.getPropertyValue("short2"))); assertTrue("Correct short2 value", new Short("2").equals(tb.getShort2())); assertTrue("Correct int2 value", new Integer("8").equals(bw.getPropertyValue("int2"))); assertTrue("Correct int2 value", new Integer("8").equals(tb.getInt2())); assertTrue("Correct long2 value", new Long("6").equals(bw.getPropertyValue("long2"))); assertTrue("Correct long2 value", new Long("6").equals(tb.getLong2())); assertTrue("Correct bigInteger value", new BigInteger("3").equals(bw.getPropertyValue("bigInteger"))); assertTrue("Correct bigInteger value", new BigInteger("3").equals(tb.getBigInteger())); assertTrue("Correct float2 value", new Float("8.1").equals(bw.getPropertyValue("float2"))); assertTrue("Correct float2 value", new Float("8.1").equals(tb.getFloat2())); assertTrue("Correct double2 value", new Double("6.1").equals(bw.getPropertyValue("double2"))); assertTrue("Correct double2 value", new Double("6.1").equals(tb.getDouble2())); assertTrue("Correct bigDecimal value", new BigDecimal("4.0").equals(bw.getPropertyValue("bigDecimal"))); assertTrue("Correct bigDecimal value", new BigDecimal("4.0").equals(tb.getBigDecimal())); } @Test public void testNumberCoercion() { NumberTestBean tb = new NumberTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); try { bw.setPropertyValue("short2", new Integer(2)); bw.setPropertyValue("int2", new Long(8)); bw.setPropertyValue("long2", new BigInteger("6")); bw.setPropertyValue("bigInteger", new Integer(3)); bw.setPropertyValue("float2", new Double(8.1)); bw.setPropertyValue("double2", new BigDecimal(6.1)); bw.setPropertyValue("bigDecimal", new Float(4.0)); } catch (BeansException ex) { fail("Should not throw BeansException: " + ex.getMessage()); } assertTrue("Correct short2 value", new Short("2").equals(bw.getPropertyValue("short2"))); assertTrue("Correct short2 value", new Short("2").equals(tb.getShort2())); assertTrue("Correct int2 value", new Integer("8").equals(bw.getPropertyValue("int2"))); assertTrue("Correct int2 value", new Integer("8").equals(tb.getInt2())); assertTrue("Correct long2 value", new Long("6").equals(bw.getPropertyValue("long2"))); assertTrue("Correct long2 value", new Long("6").equals(tb.getLong2())); assertTrue("Correct bigInteger value", new BigInteger("3").equals(bw.getPropertyValue("bigInteger"))); assertTrue("Correct bigInteger value", new BigInteger("3").equals(tb.getBigInteger())); assertTrue("Correct float2 value", new Float("8.1").equals(bw.getPropertyValue("float2"))); assertTrue("Correct float2 value", new Float("8.1").equals(tb.getFloat2())); assertTrue("Correct double2 value", new Double("6.1").equals(bw.getPropertyValue("double2"))); assertTrue("Correct double2 value", new Double("6.1").equals(tb.getDouble2())); assertTrue("Correct bigDecimal value", new BigDecimal("4.0").equals(bw.getPropertyValue("bigDecimal"))); assertTrue("Correct bigDecimal value", new BigDecimal("4.0").equals(tb.getBigDecimal())); } @Test public void testEnumByFieldName() { EnumTester et = new EnumTester(); BeanWrapper bw = new JuffrouSpringBeanWrapper(et); bw.setPropertyValue("autowire", "BY_NAME"); assertEquals(Autowire.BY_NAME, et.getAutowire()); bw.setPropertyValue("autowire", " BY_TYPE "); assertEquals(Autowire.BY_TYPE, et.getAutowire()); try { bw.setPropertyValue("autowire", "NHERITED"); fail("Should have thrown TypeMismatchException"); } catch (TypeMismatchException ex) { // expected } } @Test public void testPropertiesProperty() throws Exception { PropsTester pt = new PropsTester(); BeanWrapper bw = new JuffrouSpringBeanWrapper(pt); bw.setPropertyValue("name", "ptest"); // Note format... String ps = "peace=war\nfreedom=slavery"; bw.setPropertyValue("properties", ps); assertTrue("name was set", pt.name.equals("ptest")); assertTrue("props non null", pt.props != null); String freedomVal = pt.props.getProperty("freedom"); String peaceVal = pt.props.getProperty("peace"); assertTrue("peace==war", peaceVal.equals("war")); assertTrue("Freedom==slavery", freedomVal.equals("slavery")); } @Test public void testStringArrayProperty() throws Exception { PropsTester pt = new PropsTester(); BeanWrapper bw = new JuffrouSpringBeanWrapper(pt); bw.setPropertyValue("stringArray", new String[] { "foo", "fi", "fi", "fum" }); assertTrue("stringArray length = 4", pt.stringArray.length == 4); assertTrue("correct values", pt.stringArray[0].equals("foo") && pt.stringArray[1].equals("fi") && pt.stringArray[2].equals("fi") && pt.stringArray[3].equals("fum")); List<String> list = new ArrayList<String>(); list.add("foo"); list.add("fi"); list.add("fi"); list.add("fum"); bw.setPropertyValue("stringArray", list); assertTrue("stringArray length = 4", pt.stringArray.length == 4); assertTrue("correct values", pt.stringArray[0].equals("foo") && pt.stringArray[1].equals("fi") && pt.stringArray[2].equals("fi") && pt.stringArray[3].equals("fum")); Set<String> set = new HashSet<String>(); set.add("foo"); set.add("fi"); set.add("fum"); bw.setPropertyValue("stringArray", set); assertTrue("stringArray length = 3", pt.stringArray.length == 3); List<String> result = Arrays.asList(pt.stringArray); assertTrue("correct values", result.contains("foo") && result.contains("fi") && result.contains("fum")); bw.setPropertyValue("stringArray", "one"); assertTrue("stringArray length = 1", pt.stringArray.length == 1); assertTrue("stringArray elt is ok", pt.stringArray[0].equals("one")); bw.setPropertyValue("stringArray", null); assertTrue("stringArray is null", pt.stringArray == null); } @Test public void testStringArrayPropertyWithCustomStringEditor() throws Exception { PropsTester pt = new PropsTester(); BeanWrapper bw = new JuffrouSpringBeanWrapper(pt); bw.registerCustomEditor(String.class, "stringArray", new PropertyEditorSupport() { @Override public void setAsText(String text) { setValue(text.substring(1)); } }); bw.setPropertyValue("stringArray", new String[] { "4foo", "7fi", "6fi", "5fum" }); assertTrue("stringArray length = 4", pt.stringArray.length == 4); assertTrue("correct values", pt.stringArray[0].equals("foo") && pt.stringArray[1].equals("fi") && pt.stringArray[2].equals("fi") && pt.stringArray[3].equals("fum")); List<String> list = new ArrayList<String>(); list.add("4foo"); list.add("7fi"); list.add("6fi"); list.add("5fum"); bw.setPropertyValue("stringArray", list); assertTrue("stringArray length = 4", pt.stringArray.length == 4); assertTrue("correct values", pt.stringArray[0].equals("foo") && pt.stringArray[1].equals("fi") && pt.stringArray[2].equals("fi") && pt.stringArray[3].equals("fum")); Set<String> set = new HashSet<String>(); set.add("4foo"); set.add("7fi"); set.add("6fum"); bw.setPropertyValue("stringArray", set); assertTrue("stringArray length = 3", pt.stringArray.length == 3); List<String> result = Arrays.asList(pt.stringArray); assertTrue("correct values", result.contains("foo") && result.contains("fi") && result.contains("fum")); bw.setPropertyValue("stringArray", "8one"); assertTrue("stringArray length = 1", pt.stringArray.length == 1); assertTrue("correct values", pt.stringArray[0].equals("one")); } @Test public void testStringArrayPropertyWithStringSplitting() throws Exception { PropsTester pt = new PropsTester(); JuffrouSpringBeanWrapper bw = new JuffrouSpringBeanWrapper(pt); bw.useConfigValueEditors(); bw.setPropertyValue("stringArray", "a1,b2"); assertTrue("stringArray length = 2", pt.stringArray.length == 2); assertTrue("correct values", pt.stringArray[0].equals("a1") && pt.stringArray[1].equals("b2")); } @Test public void testStringArrayPropertyWithCustomStringDelimiter() throws Exception { PropsTester pt = new PropsTester(); BeanWrapper bw = new JuffrouSpringBeanWrapper(pt); bw.registerCustomEditor(String[].class, "stringArray", new StringArrayPropertyEditor("-")); bw.setPropertyValue("stringArray", "a1-b2"); assertTrue("stringArray length = 2", pt.stringArray.length == 2); assertTrue("correct values", pt.stringArray[0].equals("a1") && pt.stringArray[1].equals("b2")); } @Test public void testStringPropertyWithCustomEditor() throws Exception { TestBean tb = new TestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.registerCustomEditor(String.class, "name", new PropertyEditorSupport() { @Override public void setValue(Object value) { if (value instanceof String[]) { setValue(StringUtils.arrayToDelimitedString(((String[]) value), "-")); } else { super.setValue(value != null ? value : ""); } } }); bw.setPropertyValue("name", new String[] {}); assertEquals("", tb.getName()); bw.setPropertyValue("name", new String[] { "a1", "b2" }); assertEquals("a1-b2", tb.getName()); bw.setPropertyValue("name", null); assertEquals("", tb.getName()); } @Test public void testIntArrayProperty() { PropsTester pt = new PropsTester(); BeanWrapper bw = new JuffrouSpringBeanWrapper(pt); bw.setPropertyValue("intArray", new int[] { 4, 5, 2, 3 }); assertTrue("intArray length = 4", pt.intArray.length == 4); assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 && pt.intArray[2] == 2 && pt.intArray[3] == 3); bw.setPropertyValue("intArray", new String[] { "4", "5", "2", "3" }); assertTrue("intArray length = 4", pt.intArray.length == 4); assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 && pt.intArray[2] == 2 && pt.intArray[3] == 3); List<Object> list = new ArrayList<Object>(); list.add(new Integer(4)); list.add("5"); list.add(new Integer(2)); list.add("3"); bw.setPropertyValue("intArray", list); assertTrue("intArray length = 4", pt.intArray.length == 4); assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 && pt.intArray[2] == 2 && pt.intArray[3] == 3); Set<Object> set = new HashSet<Object>(); set.add("4"); set.add(new Integer(5)); set.add("3"); bw.setPropertyValue("intArray", set); assertTrue("intArray length = 3", pt.intArray.length == 3); List<Integer> result = new ArrayList<Integer>(); result.add(new Integer(pt.intArray[0])); result.add(new Integer(pt.intArray[1])); result.add(new Integer(pt.intArray[2])); assertTrue("correct values", result.contains(new Integer(4)) && result.contains(new Integer(5)) && result.contains(new Integer(3))); bw.setPropertyValue("intArray", new Integer[] { new Integer(1) }); assertTrue("intArray length = 4", pt.intArray.length == 1); assertTrue("correct values", pt.intArray[0] == 1); bw.setPropertyValue("intArray", new Integer(1)); assertTrue("intArray length = 4", pt.intArray.length == 1); assertTrue("correct values", pt.intArray[0] == 1); bw.setPropertyValue("intArray", new String[] { "1" }); assertTrue("intArray length = 4", pt.intArray.length == 1); assertTrue("correct values", pt.intArray[0] == 1); bw.setPropertyValue("intArray", "1"); assertTrue("intArray length = 4", pt.intArray.length == 1); assertTrue("correct values", pt.intArray[0] == 1); } @Test public void testIntArrayPropertyWithCustomEditor() { PropsTester pt = new PropsTester(); BeanWrapper bw = new JuffrouSpringBeanWrapper(pt); bw.registerCustomEditor(int.class, new PropertyEditorSupport() { @Override public void setAsText(String text) { setValue(new Integer(Integer.parseInt(text) + 1)); } }); bw.setPropertyValue("intArray", new int[] { 4, 5, 2, 3 }); assertTrue("intArray length = 4", pt.intArray.length == 4); assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 && pt.intArray[2] == 2 && pt.intArray[3] == 3); bw.setPropertyValue("intArray", new String[] { "3", "4", "1", "2" }); assertTrue("intArray length = 4", pt.intArray.length == 4); assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 && pt.intArray[2] == 2 && pt.intArray[3] == 3); bw.setPropertyValue("intArray", new Integer(1)); assertTrue("intArray length = 4", pt.intArray.length == 1); assertTrue("correct values", pt.intArray[0] == 1); bw.setPropertyValue("intArray", new String[] { "0" }); assertTrue("intArray length = 4", pt.intArray.length == 1); assertTrue("correct values", pt.intArray[0] == 1); bw.setPropertyValue("intArray", "0"); assertTrue("intArray length = 4", pt.intArray.length == 1); assertTrue("correct values", pt.intArray[0] == 1); } @Test public void testIntArrayPropertyWithStringSplitting() throws Exception { PropsTester pt = new PropsTester(); JuffrouSpringBeanWrapper bw = new JuffrouSpringBeanWrapper(pt); bw.useConfigValueEditors(); bw.setPropertyValue("intArray", "4,5"); assertTrue("intArray length = 2", pt.intArray.length == 2); assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5); } @Test public void testIndividualAllValid() { TestBean t = new TestBean(); String newName = "tony"; int newAge = 65; String newTouchy = "valid"; try { BeanWrapper bw = new JuffrouSpringBeanWrapper(t); bw.setPropertyValue("age", new Integer(newAge)); bw.setPropertyValue(new PropertyValue("name", newName)); bw.setPropertyValue(new PropertyValue("touchy", newTouchy)); assertTrue("Validly set property must stick", t.getName().equals(newName)); assertTrue("Validly set property must stick", t.getTouchy().equals(newTouchy)); assertTrue("Validly set property must stick", t.getAge() == newAge); } catch (BeansException ex) { fail("Shouldn't throw exception when everything is valid"); } } @Test public void test2Invalid() { TestBean t = new TestBean(); String newName = "tony"; String invalidTouchy = ".valid"; try { BeanWrapper bw = new JuffrouSpringBeanWrapper(t); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValue(new PropertyValue("age", "foobar")); pvs.addPropertyValue(new PropertyValue("name", newName)); pvs.addPropertyValue(new PropertyValue("touchy", invalidTouchy)); bw.setPropertyValues(pvs); fail("Should throw exception when everything is valid"); } catch (PropertyBatchUpdateException ex) { assertTrue("Must contain 2 exceptions", ex.getExceptionCount() == 2); // Test validly set property matches assertTrue("Validly set property must stick", t.getName().equals(newName)); assertTrue("Invalidly set property must retain old value", t.getAge() == 0); assertTrue("New value of dodgy setter must be available through exception", ex.getPropertyAccessException("touchy").getPropertyChangeEvent().getNewValue() .equals(invalidTouchy)); } } @Test public void testPossibleMatches() { TestBean tb = new TestBean(); try { BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.setPropertyValue("ag", "foobar"); fail("Should throw exception on invalid property"); } catch (NotWritablePropertyException ex) { // expected assertEquals(1, ex.getPossibleMatches().length); assertEquals("age", ex.getPossibleMatches()[0]); } } @Test public void testTypeMismatch() { TestBean t = new TestBean(); try { BeanWrapper bw = new JuffrouSpringBeanWrapper(t); bw.setPropertyValue("age", "foobar"); fail("Should throw exception on type mismatch"); } catch (TypeMismatchException ex) { // expected } } @Test public void testEmptyValueForPrimitiveProperty() { TestBean t = new TestBean(); try { BeanWrapper bw = new JuffrouSpringBeanWrapper(t); bw.setPropertyValue("age", ""); fail("Should throw exception on type mismatch"); } catch (TypeMismatchException ex) { // expected } catch (Exception ex) { fail("Shouldn't throw exception other than Type mismatch"); } } @Test public void testSetPropertyValuesIgnoresInvalidNestedOnRequest() { ITestBean rod = new TestBean(); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValue(new PropertyValue("name", "rod")); pvs.addPropertyValue(new PropertyValue("graceful.rubbish", "tony")); pvs.addPropertyValue(new PropertyValue("more.garbage", new Object())); BeanWrapper bw = new JuffrouSpringBeanWrapper(rod); bw.setPropertyValues(pvs, true); assertTrue("Set valid and ignored invalid", rod.getName().equals("rod")); try { // Don't ignore: should fail bw.setPropertyValues(pvs, false); fail("Shouldn't have ignored invalid updates"); } catch (NotWritablePropertyException ex) { // OK: but which exception?? } } @Test public void testGetNestedProperty() { ITestBean rod = new TestBean("rod", 31); ITestBean kerry = new TestBean("kerry", 35); rod.setSpouse(kerry); kerry.setSpouse(rod); BeanWrapper bw = new JuffrouSpringBeanWrapper(rod); Integer KA = (Integer) bw.getPropertyValue("spouse.age"); assertTrue("kerry is 35", KA.intValue() == 35); Integer RA = (Integer) bw.getPropertyValue("spouse.spouse.age"); assertTrue("rod is 31, not" + RA, RA.intValue() == 31); ITestBean spousesSpouse = (ITestBean) bw.getPropertyValue("spouse.spouse"); assertTrue("spousesSpouse = initial point", rod == spousesSpouse); } @Test public void testGetNestedPropertyNullValue() throws Exception { ITestBean rod = new TestBean("rod", 31); ITestBean kerry = new TestBean("kerry", 35); rod.setSpouse(kerry); BeanWrapper bw = new JuffrouSpringBeanWrapper(rod); try { bw.getPropertyValue("spouse.spouse.age"); fail("Shouldn't have succeded with null path"); } catch (NullValueInNestedPathException ex) { // ok assertTrue("it was the spouse.spouse property that was null, not " + ex.getPropertyName(), ex.getPropertyName().equals("spouse.spouse")); } } @Test public void testSetNestedProperty() throws Exception { ITestBean rod = new TestBean("rod", 31); ITestBean kerry = new TestBean("kerry", 0); BeanWrapper bw = new JuffrouSpringBeanWrapper(rod); bw.setPropertyValue("spouse", kerry); assertTrue("nested set worked", rod.getSpouse() == kerry); assertTrue("no back relation", kerry.getSpouse() == null); bw.setPropertyValue(new PropertyValue("spouse.spouse", rod)); assertTrue("nested set worked", kerry.getSpouse() == rod); assertTrue("kerry age not set", kerry.getAge() == 0); bw.setPropertyValue(new PropertyValue("spouse.age", new Integer(35))); assertTrue("Set primitive on spouse", kerry.getAge() == 35); assertEquals(kerry, bw.getPropertyValue("spouse")); assertEquals(rod, bw.getPropertyValue("spouse.spouse")); } @Test public void testSetNestedPropertyNullValue() throws Exception { ITestBean rod = new TestBean("rod", 31); BeanWrapper bw = new JuffrouSpringBeanWrapper(rod); try { bw.setPropertyValue("spouse.age", new Integer(31)); fail("Shouldn't have succeeded with null path"); } catch (NullValueInNestedPathException ex) { // expected assertTrue("it was the spouse property that was null, not " + ex.getPropertyName(), ex.getPropertyName().equals("spouse")); } } @Test public void testSetNestedPropertyPolymorphic() throws Exception { ITestBean rod = new TestBean("rod", 31); ITestBean kerry = new Employee(); BeanWrapper bw = new JuffrouSpringBeanWrapper(rod); bw.setPropertyValue("spouse", kerry); bw.setPropertyValue("spouse.age", new Integer(35)); bw.setPropertyValue("spouse.name", "Kerry"); bw.setPropertyValue("spouse.company", "Lewisham"); assertTrue("kerry name is Kerry", kerry.getName().equals("Kerry")); assertTrue("nested set worked", rod.getSpouse() == kerry); assertTrue("no back relation", kerry.getSpouse() == null); bw.setPropertyValue(new PropertyValue("spouse.spouse", rod)); assertTrue("nested set worked", kerry.getSpouse() == rod); BeanWrapper kbw = new JuffrouSpringBeanWrapper(kerry); assertTrue("spouse.spouse.spouse.spouse.company=Lewisham", "Lewisham".equals(kbw.getPropertyValue("spouse.spouse.spouse.spouse.company"))); } @Test public void testNullObject() { try { new JuffrouSpringBeanWrapper((Object) null); fail("Must throw an exception when constructed with null object"); } catch (IllegalArgumentException ex) { // expected } } @Test public void testNestedProperties() { String doctorCompany = ""; String lawyerCompany = "Dr. Sueem"; TestBean tb = new TestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.setPropertyValue("doctor.company", doctorCompany); bw.setPropertyValue("lawyer.company", lawyerCompany); assertEquals(doctorCompany, tb.getDoctor().getCompany()); assertEquals(lawyerCompany, tb.getLawyer().getCompany()); } @Test public void testIndexedProperties() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); TestBean tb0 = bean.getArray()[0]; TestBean tb1 = bean.getArray()[1]; TestBean tb2 = ((TestBean) bean.getList().get(0)); TestBean tb3 = ((TestBean) bean.getList().get(1)); TestBean tb6 = ((TestBean) bean.getSet().toArray()[0]); TestBean tb7 = ((TestBean) bean.getSet().toArray()[1]); TestBean tb4 = ((TestBean) bean.getMap().get("key1")); TestBean tb5 = ((TestBean) bean.getMap().get("key.3")); assertEquals("name0", tb0.getName()); assertEquals("name1", tb1.getName()); assertEquals("name2", tb2.getName()); assertEquals("name3", tb3.getName()); assertEquals("name6", tb6.getName()); assertEquals("name7", tb7.getName()); assertEquals("name4", tb4.getName()); assertEquals("name5", tb5.getName()); assertEquals("name0", bw.getPropertyValue("array[0].name")); assertEquals("name1", bw.getPropertyValue("array[1].name")); assertEquals("name2", bw.getPropertyValue("list[0].name")); assertEquals("name3", bw.getPropertyValue("list[1].name")); assertEquals("name6", bw.getPropertyValue("set[0].name")); assertEquals("name7", bw.getPropertyValue("set[1].name")); assertEquals("name4", bw.getPropertyValue("map[key1].name")); assertEquals("name5", bw.getPropertyValue("map[key.3].name")); assertEquals("name4", bw.getPropertyValue("map['key1'].name")); assertEquals("name5", bw.getPropertyValue("map[\"key.3\"].name")); assertEquals("nameX", bw.getPropertyValue("map[key4][0].name")); assertEquals("nameY", bw.getPropertyValue("map[key4][1].name")); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("array[0].name", "name5"); pvs.add("array[1].name", "name4"); pvs.add("list[0].name", "name3"); pvs.add("list[1].name", "name2"); pvs.add("set[0].name", "name8"); pvs.add("set[1].name", "name9"); pvs.add("map[key1].name", "name1"); pvs.add("map['key.3'].name", "name0"); pvs.add("map[key4][0].name", "nameA"); pvs.add("map[key4][1].name", "nameB"); bw.setPropertyValues(pvs); assertEquals("name5", tb0.getName()); assertEquals("name4", tb1.getName()); assertEquals("name3", tb2.getName()); assertEquals("name2", tb3.getName()); assertEquals("name1", tb4.getName()); assertEquals("name0", tb5.getName()); assertEquals("name5", bw.getPropertyValue("array[0].name")); assertEquals("name4", bw.getPropertyValue("array[1].name")); assertEquals("name3", bw.getPropertyValue("list[0].name")); assertEquals("name2", bw.getPropertyValue("list[1].name")); assertEquals("name8", bw.getPropertyValue("set[0].name")); assertEquals("name9", bw.getPropertyValue("set[1].name")); assertEquals("name1", bw.getPropertyValue("map[\"key1\"].name")); assertEquals("name0", bw.getPropertyValue("map['key.3'].name")); assertEquals("nameA", bw.getPropertyValue("map[key4][0].name")); assertEquals("nameB", bw.getPropertyValue("map[key4][1].name")); } @Test public void testIndexedPropertiesWithDirectAccess() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); TestBean tb0 = bean.getArray()[0]; TestBean tb1 = bean.getArray()[1]; TestBean tb2 = ((TestBean) bean.getList().get(0)); TestBean tb3 = ((TestBean) bean.getList().get(1)); TestBean tb6 = ((TestBean) bean.getSet().toArray()[0]); TestBean tb7 = ((TestBean) bean.getSet().toArray()[1]); TestBean tb4 = ((TestBean) bean.getMap().get("key1")); TestBean tb5 = ((TestBean) bean.getMap().get("key2")); assertEquals(tb0, bw.getPropertyValue("array[0]")); assertEquals(tb1, bw.getPropertyValue("array[1]")); assertEquals(tb2, bw.getPropertyValue("list[0]")); assertEquals(tb3, bw.getPropertyValue("list[1]")); assertEquals(tb6, bw.getPropertyValue("set[0]")); assertEquals(tb7, bw.getPropertyValue("set[1]")); assertEquals(tb4, bw.getPropertyValue("map[key1]")); assertEquals(tb5, bw.getPropertyValue("map[key2]")); assertEquals(tb4, bw.getPropertyValue("map['key1']")); assertEquals(tb5, bw.getPropertyValue("map[\"key2\"]")); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("array[0]", tb5); pvs.add("array[1]", tb4); pvs.add("list[0]", tb3); pvs.add("list[1]", tb2); pvs.add("list[2]", tb0); pvs.add("list[4]", tb1); pvs.add("map[key1]", tb1); pvs.add("map['key2']", tb0); pvs.add("map[key5]", tb4); pvs.add("map['key9']", tb5); bw.setPropertyValues(pvs); assertEquals(tb5, bean.getArray()[0]); assertEquals(tb4, bean.getArray()[1]); assertEquals(tb3, (bean.getList().get(0))); assertEquals(tb2, (bean.getList().get(1))); assertEquals(tb0, (bean.getList().get(2))); assertEquals(null, (bean.getList().get(3))); assertEquals(tb1, (bean.getList().get(4))); assertEquals(tb1, (bean.getMap().get("key1"))); assertEquals(tb0, (bean.getMap().get("key2"))); assertEquals(tb4, (bean.getMap().get("key5"))); assertEquals(tb5, (bean.getMap().get("key9"))); assertEquals(tb5, bw.getPropertyValue("array[0]")); assertEquals(tb4, bw.getPropertyValue("array[1]")); assertEquals(tb3, bw.getPropertyValue("list[0]")); assertEquals(tb2, bw.getPropertyValue("list[1]")); assertEquals(tb0, bw.getPropertyValue("list[2]")); assertEquals(null, bw.getPropertyValue("list[3]")); assertEquals(tb1, bw.getPropertyValue("list[4]")); assertEquals(tb1, bw.getPropertyValue("map[\"key1\"]")); assertEquals(tb0, bw.getPropertyValue("map['key2']")); assertEquals(tb4, bw.getPropertyValue("map[\"key5\"]")); assertEquals(tb5, bw.getPropertyValue("map['key9']")); } @Test public void testMapAccessWithTypeConversion() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); bw.registerCustomEditor(TestBean.class, new PropertyEditorSupport() { @Override public void setAsText(String text) throws IllegalArgumentException { if (!StringUtils.hasLength(text)) { throw new IllegalArgumentException(); } setValue(new TestBean(text)); } }); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("map[key1]", "rod"); pvs.add("map[key2]", "rob"); bw.setPropertyValues(pvs); assertEquals("rod", ((TestBean) bean.getMap().get("key1")).getName()); assertEquals("rob", ((TestBean) bean.getMap().get("key2")).getName()); pvs = new MutablePropertyValues(); pvs.add("map[key1]", "rod"); pvs.add("map[key2]", ""); try { bw.setPropertyValues(pvs); fail("Should have thrown TypeMismatchException"); } catch (PropertyBatchUpdateException ex) { PropertyAccessException pae = ex.getPropertyAccessException("map[key2]"); assertTrue(pae instanceof TypeMismatchException); } } @Test public void testMapAccessWithUnmodifiableMap() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); bw.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() { @Override public void setAsText(String text) throws IllegalArgumentException { if (!StringUtils.hasLength(text)) { throw new IllegalArgumentException(); } setValue(new TestBean(text)); } }); Map<Integer, String> inputMap = new HashMap<Integer, String>(); inputMap.put(new Integer(1), "rod"); inputMap.put(new Integer(2), "rob"); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("map", Collections.unmodifiableMap(inputMap)); bw.setPropertyValues(pvs); assertEquals("rod", ((TestBean) bean.getMap().get(new Integer(1))).getName()); assertEquals("rob", ((TestBean) bean.getMap().get(new Integer(2))).getName()); } @Test public void testMapAccessWithCustomUnmodifiableMap() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); bw.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() { @Override public void setAsText(String text) throws IllegalArgumentException { if (!StringUtils.hasLength(text)) { throw new IllegalArgumentException(); } setValue(new TestBean(text)); } }); Map<Object, Object> inputMap = new HashMap<Object, Object>(); inputMap.put(new Integer(1), "rod"); inputMap.put(new Integer(2), "rob"); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("map", new ReadOnlyMap(inputMap)); bw.setPropertyValues(pvs); assertEquals("rod", ((TestBean) bean.getMap().get(new Integer(1))).getName()); assertEquals("rob", ((TestBean) bean.getMap().get(new Integer(2))).getName()); } @SuppressWarnings("unchecked") // must work with raw map in this test @Test public void testRawMapAccessWithNoEditorRegistered() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); Map inputMap = new HashMap(); inputMap.put(new Integer(1), "rod"); inputMap.put(new Integer(2), "rob"); ReadOnlyMap readOnlyMap = new ReadOnlyMap(inputMap); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.add("map", readOnlyMap); bw.setPropertyValues(pvs); assertSame(readOnlyMap, bean.getMap()); assertFalse(readOnlyMap.isAccessed()); } @Test public void testTypedMapReadOnlyMap() { TypedReadOnlyMap map = new TypedReadOnlyMap(Collections.singletonMap("key", new TestBean())); TypedReadOnlyMapClient bean = new TypedReadOnlyMapClient(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); bw.setPropertyValue("map", map); } @Test public void testPrimitiveArray() { PrimitiveArrayBean tb = new PrimitiveArrayBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.setPropertyValue("array", new String[] { "1", "2" }); assertEquals(2, tb.getArray().length); assertEquals(1, tb.getArray()[0]); assertEquals(2, tb.getArray()[1]); } @Test public void testLargeMatchingPrimitiveArray() { if (LogFactory.getLog(BeanWrapperTests.class).isTraceEnabled()) { // Skip this test: Trace logging blows the time limit. return; } PrimitiveArrayBean tb = new PrimitiveArrayBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); int[] input = new int[1024]; StopWatch sw = new StopWatch(); sw.start("array1"); for (int i = 0; i < 1000; i++) { bw.setPropertyValue("array", input); } sw.stop(); assertEquals(1024, tb.getArray().length); assertEquals(0, tb.getArray()[0]); long time1 = sw.getLastTaskTimeMillis(); assertTrue("Took too long", sw.getLastTaskTimeMillis() < 100); bw.registerCustomEditor(String.class, new StringTrimmerEditor(false)); sw.start("array2"); for (int i = 0; i < 1000; i++) { bw.setPropertyValue("array", input); } sw.stop(); assertTrue("Took too long", sw.getLastTaskTimeMillis() < 125); bw.registerCustomEditor(int.class, "array.somePath", new CustomNumberEditor(Integer.class, false)); sw.start("array3"); for (int i = 0; i < 1000; i++) { bw.setPropertyValue("array", input); } sw.stop(); assertTrue("Took too long", sw.getLastTaskTimeMillis() < 100); bw.registerCustomEditor(int.class, "array[0].somePath", new CustomNumberEditor(Integer.class, false)); sw.start("array3"); for (int i = 0; i < 1000; i++) { bw.setPropertyValue("array", input); } sw.stop(); assertTrue("Took too long", sw.getLastTaskTimeMillis() < 100); bw.registerCustomEditor(int.class, new CustomNumberEditor(Integer.class, false)); sw.start("array4"); for (int i = 0; i < 100; i++) { bw.setPropertyValue("array", input); } sw.stop(); assertEquals(1024, tb.getArray().length); assertEquals(0, tb.getArray()[0]); assertTrue("Took too long", sw.getLastTaskTimeMillis() > time1); } @Test public void testLargeMatchingPrimitiveArrayWithSpecificEditor() { PrimitiveArrayBean tb = new PrimitiveArrayBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.registerCustomEditor(int.class, "array", new PropertyEditorSupport() { @Override public void setValue(Object value) { if (value instanceof Integer) { super.setValue(new Integer(((Integer) value).intValue() + 1)); } } }); int[] input = new int[1024]; bw.setPropertyValue("array", input); assertEquals(1024, tb.getArray().length); assertEquals(1, tb.getArray()[0]); assertEquals(1, tb.getArray()[1]); } @Test public void testLargeMatchingPrimitiveArrayWithIndexSpecificEditor() { PrimitiveArrayBean tb = new PrimitiveArrayBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.registerCustomEditor(int.class, "array[1]", new PropertyEditorSupport() { @Override public void setValue(Object value) { if (value instanceof Integer) { super.setValue(new Integer(((Integer) value).intValue() + 1)); } } }); int[] input = new int[1024]; bw.setPropertyValue("array", input); assertEquals(1024, tb.getArray().length); assertEquals(0, tb.getArray()[0]); assertEquals(1, tb.getArray()[1]); } /* @Test public void testPropertiesInProtectedBaseBean() { DerivedFromProtectedBaseBean bean = new DerivedFromProtectedBaseBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); bw.setPropertyValue("someProperty", "someValue"); assertEquals("someValue", bw.getPropertyValue("someProperty")); assertEquals("someValue", bean.getSomeProperty()); } */ @Test public void testErrorMessageOfNestedProperty() { ITestBean parent = new TestBean(); ITestBean child = new DifferentTestBean(); child.setName("test"); parent.setSpouse(child); BeanWrapper bw = new JuffrouSpringBeanWrapper(parent); try { bw.getPropertyValue("spouse.bla"); } catch (NotReadablePropertyException ex) { assertTrue(ex.getMessage().indexOf(TestBean.class.getName()) != -1); } } @Test public void testMatchingCollections() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); Collection<String> coll = new HashSet<String>(); coll.add("coll1"); bw.setPropertyValue("collection", coll); Set<String> set = new HashSet<String>(); set.add("set1"); bw.setPropertyValue("set", set); SortedSet<String> sortedSet = new TreeSet<String>(); sortedSet.add("sortedSet1"); bw.setPropertyValue("sortedSet", sortedSet); List<String> list = new LinkedList<String>(); list.add("list1"); bw.setPropertyValue("list", list); assertSame(coll, tb.getCollection()); assertSame(set, tb.getSet()); assertSame(sortedSet, tb.getSortedSet()); assertSame(list, tb.getList()); } @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test public void testNonMatchingCollections() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); Collection<String> coll = new ArrayList<String>(); coll.add("coll1"); bw.setPropertyValue("collection", coll); List<String> set = new LinkedList<String>(); set.add("set1"); bw.setPropertyValue("set", set); List<String> sortedSet = new ArrayList<String>(); sortedSet.add("sortedSet1"); bw.setPropertyValue("sortedSet", sortedSet); Set<String> list = new HashSet<String>(); list.add("list1"); bw.setPropertyValue("list", list); assertEquals(1, tb.getCollection().size()); assertTrue(tb.getCollection().containsAll(coll)); assertEquals(1, tb.getSet().size()); assertTrue(tb.getSet().containsAll(set)); assertEquals(1, tb.getSortedSet().size()); assertTrue(tb.getSortedSet().containsAll(sortedSet)); assertEquals(1, tb.getList().size()); assertTrue(tb.getList().containsAll(list)); } @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test public void testCollectionsWithArrayValues() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); Collection<String> coll = new HashSet<String>(); coll.add("coll1"); bw.setPropertyValue("collection", coll.toArray()); List<String> set = new LinkedList<String>(); set.add("set1"); bw.setPropertyValue("set", set.toArray()); List<String> sortedSet = new ArrayList<String>(); sortedSet.add("sortedSet1"); bw.setPropertyValue("sortedSet", sortedSet.toArray()); Set<String> list = new HashSet<String>(); list.add("list1"); bw.setPropertyValue("list", list.toArray()); assertEquals(1, tb.getCollection().size()); assertTrue(tb.getCollection().containsAll(coll)); assertEquals(1, tb.getSet().size()); assertTrue(tb.getSet().containsAll(set)); assertEquals(1, tb.getSortedSet().size()); assertTrue(tb.getSortedSet().containsAll(sortedSet)); assertEquals(1, tb.getList().size()); assertTrue(tb.getList().containsAll(list)); } @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test public void testCollectionsWithIntArrayValues() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); Collection<Integer> coll = new HashSet<Integer>(); coll.add(new Integer(0)); bw.setPropertyValue("collection", new int[] { 0 }); List<Integer> set = new LinkedList<Integer>(); set.add(new Integer(1)); bw.setPropertyValue("set", new int[] { 1 }); List<Integer> sortedSet = new ArrayList<Integer>(); sortedSet.add(new Integer(2)); bw.setPropertyValue("sortedSet", new int[] { 2 }); Set<Integer> list = new HashSet<Integer>(); list.add(new Integer(3)); bw.setPropertyValue("list", new int[] { 3 }); assertEquals(1, tb.getCollection().size()); assertTrue(tb.getCollection().containsAll(coll)); assertEquals(1, tb.getSet().size()); assertTrue(tb.getSet().containsAll(set)); assertEquals(1, tb.getSortedSet().size()); assertTrue(tb.getSortedSet().containsAll(sortedSet)); assertEquals(1, tb.getList().size()); assertTrue(tb.getList().containsAll(list)); } @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test public void testCollectionsWithIntegerValues() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); Collection<Integer> coll = new HashSet<Integer>(); coll.add(new Integer(0)); bw.setPropertyValue("collection", new Integer(0)); List<Integer> set = new LinkedList<Integer>(); set.add(new Integer(1)); bw.setPropertyValue("set", new Integer(1)); List<Integer> sortedSet = new ArrayList<Integer>(); sortedSet.add(new Integer(2)); bw.setPropertyValue("sortedSet", new Integer(2)); Set<Integer> list = new HashSet<Integer>(); list.add(new Integer(3)); bw.setPropertyValue("list", new Integer(3)); assertEquals(1, tb.getCollection().size()); assertTrue(tb.getCollection().containsAll(coll)); assertEquals(1, tb.getSet().size()); assertTrue(tb.getSet().containsAll(set)); assertEquals(1, tb.getSortedSet().size()); assertTrue(tb.getSortedSet().containsAll(sortedSet)); assertEquals(1, tb.getList().size()); assertTrue(tb.getList().containsAll(list)); } @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test public void testCollectionsWithStringValues() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); List<String> set = new LinkedList<String>(); set.add("set1"); bw.setPropertyValue("set", "set1"); List<String> sortedSet = new ArrayList<String>(); sortedSet.add("sortedSet1"); bw.setPropertyValue("sortedSet", "sortedSet1"); Set<String> list = new HashSet<String>(); list.add("list1"); bw.setPropertyValue("list", "list1"); assertEquals(1, tb.getSet().size()); assertTrue(tb.getSet().containsAll(set)); assertEquals(1, tb.getSortedSet().size()); assertTrue(tb.getSortedSet().containsAll(sortedSet)); assertEquals(1, tb.getList().size()); assertTrue(tb.getList().containsAll(list)); } @Test public void testCollectionsWithStringValuesAndCustomEditor() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); bw.registerCustomEditor(String.class, "set", new StringTrimmerEditor(false)); bw.registerCustomEditor(String.class, "list", new StringTrimmerEditor(false)); bw.setPropertyValue("set", "set1 "); bw.setPropertyValue("sortedSet", "sortedSet1"); bw.setPropertyValue("list", "list1 "); assertEquals(1, tb.getSet().size()); assertTrue(tb.getSet().contains("set1")); assertEquals(1, tb.getSortedSet().size()); assertTrue(tb.getSortedSet().contains("sortedSet1")); assertEquals(1, tb.getList().size()); assertTrue(tb.getList().contains("list1")); bw.setPropertyValue("list", Arrays.asList(new String[] { "list1 " })); assertTrue(tb.getList().contains("list1")); } @Test public void testMatchingMaps() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); Map<String, String> map = new HashMap<String, String>(); map.put("key", "value"); bw.setPropertyValue("map", map); SortedMap<?, ?> sortedMap = new TreeMap<Object, Object>(); map.put("sortedKey", "sortedValue"); bw.setPropertyValue("sortedMap", sortedMap); assertSame(map, tb.getMap()); assertSame(sortedMap, tb.getSortedMap()); } @Test public void testNonMatchingMaps() { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(tb); Map<String, String> map = new TreeMap<String, String>(); map.put("key", "value"); bw.setPropertyValue("map", map); Map<String, String> sortedMap = new TreeMap<String, String>(); sortedMap.put("sortedKey", "sortedValue"); bw.setPropertyValue("sortedMap", sortedMap); assertEquals(1, tb.getMap().size()); assertEquals("value", tb.getMap().get("key")); assertEquals(1, tb.getSortedMap().size()); assertEquals("sortedValue", tb.getSortedMap().get("sortedKey")); } @Test public void testSetNumberProperties() { NumberPropertyBean bean = new NumberPropertyBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(bean); String byteValue = " " + Byte.MAX_VALUE + " "; String shortValue = " " + Short.MAX_VALUE + " "; String intValue = " " + Integer.MAX_VALUE + " "; String longValue = " " + Long.MAX_VALUE + " "; String floatValue = " " + Float.MAX_VALUE + " "; String doubleValue = " " + Double.MAX_VALUE + " "; bw.setPropertyValue("myPrimitiveByte", byteValue); bw.setPropertyValue("myByte", byteValue); bw.setPropertyValue("myPrimitiveShort", shortValue); bw.setPropertyValue("myShort", shortValue); bw.setPropertyValue("myPrimitiveInt", intValue); bw.setPropertyValue("myInteger", intValue); bw.setPropertyValue("myPrimitiveLong", longValue); bw.setPropertyValue("myLong", longValue); bw.setPropertyValue("myPrimitiveFloat", floatValue); bw.setPropertyValue("myFloat", floatValue); bw.setPropertyValue("myPrimitiveDouble", doubleValue); bw.setPropertyValue("myDouble", doubleValue); assertEquals(Byte.MAX_VALUE, bean.getMyPrimitiveByte()); assertEquals(Byte.MAX_VALUE, bean.getMyByte().byteValue()); assertEquals(Short.MAX_VALUE, bean.getMyPrimitiveShort()); assertEquals(Short.MAX_VALUE, bean.getMyShort().shortValue()); assertEquals(Integer.MAX_VALUE, bean.getMyPrimitiveInt()); assertEquals(Integer.MAX_VALUE, bean.getMyInteger().intValue()); assertEquals(Long.MAX_VALUE, bean.getMyPrimitiveLong()); assertEquals(Long.MAX_VALUE, bean.getMyLong().longValue()); assertEquals(Float.MAX_VALUE, bean.getMyPrimitiveFloat(), 0.001); assertEquals(Float.MAX_VALUE, bean.getMyFloat().floatValue(), 0.001); assertEquals(Double.MAX_VALUE, bean.getMyPrimitiveDouble(), 0.001); assertEquals(Double.MAX_VALUE, bean.getMyDouble().doubleValue(), 0.001); } @Test public void testAlternativesForTypo() { IntelliBean ib = new IntelliBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(ib); try { bw.setPropertyValue("names", "Alef"); } catch (NotWritablePropertyException ex) { assertNotNull("Possible matches not determined", ex.getPossibleMatches()); assertEquals("Invalid amount of alternatives", 1, ex.getPossibleMatches().length); } } @Test public void testAlternativesForTypos() { IntelliBean ib = new IntelliBean(); BeanWrapper bw = new JuffrouSpringBeanWrapper(ib); try { bw.setPropertyValue("mystring", "Arjen"); } catch (NotWritablePropertyException ex) { assertNotNull("Possible matches not determined", ex.getPossibleMatches()); assertEquals("Invalid amount of alternatives", 3, ex.getPossibleMatches().length); } } @Test public void testGenericEnum() { EnumConsumer consumer = new EnumConsumer(); BeanWrapper bw = new JuffrouSpringBeanWrapper(consumer); bw.setPropertyValue("enumValue", TestEnum.class.getName() + ".TEST_VALUE"); assertEquals(TestEnum.TEST_VALUE, consumer.getEnumValue()); } @Test public void testWildcardedGenericEnum() { WildcardEnumConsumer consumer = new WildcardEnumConsumer(); BeanWrapper bw = new JuffrouSpringBeanWrapper(consumer); bw.setPropertyValue("enumValue", TestEnum.class.getName() + ".TEST_VALUE"); assertEquals(TestEnum.TEST_VALUE, consumer.getEnumValue()); } private static class Foo { private List list; private List<Map> listOfMaps; public List getList() { return list; } public void setList(List list) { this.list = list; } public List<Map> getListOfMaps() { return listOfMaps; } public void setListOfMaps(List<Map> listOfMaps) { this.listOfMaps = listOfMaps; } } private static class DifferentTestBean extends TestBean { // class to test naming of beans in a BeanWrapper error message } private static class NoRead { public void setAge(int age) { } } private static class EnumTester { private Autowire autowire; public void setAutowire(Autowire autowire) { this.autowire = autowire; } public Autowire getAutowire() { return autowire; } } private static class PropsTester { private Properties props; private String name; private String[] stringArray; private int[] intArray; public void setProperties(Properties p) { props = p; } public void setName(String name) { this.name = name; } public void setStringArray(String[] sa) { this.stringArray = sa; } public void setIntArray(int[] intArray) { this.intArray = intArray; } } private static class GetterBean { private String name; public void setName(String name) { this.name = name; } public String getName() { if (this.name == null) { throw new RuntimeException("name property must be set"); } return name; } } private static class ThrowsException { public void doSomething(Throwable t) throws Throwable { throw t; } } private static class PrimitiveArrayBean { private int[] array; public int[] getArray() { return array; } public void setArray(int[] array) { this.array = array; } } private static class NumberPropertyBean { private byte myPrimitiveByte; private Byte myByte; private short myPrimitiveShort; private Short myShort; private int myPrimitiveInt; private Integer myInteger; private long myPrimitiveLong; private Long myLong; private float myPrimitiveFloat; private Float myFloat; private double myPrimitiveDouble; private Double myDouble; public byte getMyPrimitiveByte() { return myPrimitiveByte; } public void setMyPrimitiveByte(byte myPrimitiveByte) { this.myPrimitiveByte = myPrimitiveByte; } public Byte getMyByte() { return myByte; } public void setMyByte(Byte myByte) { this.myByte = myByte; } public short getMyPrimitiveShort() { return myPrimitiveShort; } public void setMyPrimitiveShort(short myPrimitiveShort) { this.myPrimitiveShort = myPrimitiveShort; } public Short getMyShort() { return myShort; } public void setMyShort(Short myShort) { this.myShort = myShort; } public int getMyPrimitiveInt() { return myPrimitiveInt; } public void setMyPrimitiveInt(int myPrimitiveInt) { this.myPrimitiveInt = myPrimitiveInt; } public Integer getMyInteger() { return myInteger; } public void setMyInteger(Integer myInteger) { this.myInteger = myInteger; } public long getMyPrimitiveLong() { return myPrimitiveLong; } public void setMyPrimitiveLong(long myPrimitiveLong) { this.myPrimitiveLong = myPrimitiveLong; } public Long getMyLong() { return myLong; } public void setMyLong(Long myLong) { this.myLong = myLong; } public float getMyPrimitiveFloat() { return myPrimitiveFloat; } public void setMyPrimitiveFloat(float myPrimitiveFloat) { this.myPrimitiveFloat = myPrimitiveFloat; } public Float getMyFloat() { return myFloat; } public void setMyFloat(Float myFloat) { this.myFloat = myFloat; } public double getMyPrimitiveDouble() { return myPrimitiveDouble; } public void setMyPrimitiveDouble(double myPrimitiveDouble) { this.myPrimitiveDouble = myPrimitiveDouble; } public Double getMyDouble() { return myDouble; } public void setMyDouble(Double myDouble) { this.myDouble = myDouble; } } private static class IntelliBean { public void setName(String name) { } public void setMyString(String string) { } public void setMyStrings(String string) { } public void setMyStriNg(String string) { } public void setMyStringss(String string) { } } private static class Employee extends TestBean { private String co; public String getCompany() { return co; } public void setCompany(String co) { this.co = co; } } @SuppressWarnings("serial") public static class ReadOnlyMap<K, V> extends HashMap<K, V> { private boolean frozen = false; private boolean accessed = false; public ReadOnlyMap() { this.frozen = true; } public ReadOnlyMap(Map<? extends K, ? extends V> map) { super(map); this.frozen = true; } @Override public V put(K key, V value) { if (this.frozen) { throw new UnsupportedOperationException(); } else { return super.put(key, value); } } @Override public Set<Map.Entry<K, V>> entrySet() { this.accessed = true; return super.entrySet(); } @Override public Set<K> keySet() { this.accessed = true; return super.keySet(); } @Override public int size() { this.accessed = true; return super.size(); } public boolean isAccessed() { return this.accessed; } } public static class TypedReadOnlyMap extends ReadOnlyMap<String, TestBean> { public TypedReadOnlyMap() { } public TypedReadOnlyMap(Map<? extends String, ? extends TestBean> map) { super(map); } } public static class TypedReadOnlyMapClient { public void setMap(TypedReadOnlyMap map) { } } public static class EnumConsumer { private Enum<TestEnum> enumValue; public Enum<TestEnum> getEnumValue() { return enumValue; } public void setEnumValue(Enum<TestEnum> enumValue) { this.enumValue = enumValue; } } public static class WildcardEnumConsumer { private Enum<?> enumValue; public Enum<?> getEnumValue() { return enumValue; } public void setEnumValue(Enum<?> enumValue) { this.enumValue = enumValue; } } public enum TestEnum { TEST_VALUE } }