ObjectProperty and MethodProperty no longer try to automatically convert values using a String constructor of the property type. Related fixes to tests.tags/7.0.0.alpha1
@@ -5,7 +5,6 @@ | |||
package com.vaadin.data.util; | |||
import java.io.IOException; | |||
import java.lang.reflect.Constructor; | |||
import java.lang.reflect.InvocationTargetException; | |||
import java.lang.reflect.Method; | |||
import java.util.logging.Level; | |||
@@ -630,9 +629,10 @@ public class MethodProperty<T> extends AbstractProperty<T> { | |||
} | |||
/** | |||
* Sets the value of the property. This method supports setting from | |||
* <code>String</code>s if either <code>String</code> is directly assignable | |||
* to property type, or the type class contains a string constructor. | |||
* Sets the value of the property. | |||
* | |||
* Note that since Vaadin 7, no conversions are performed and the value must | |||
* be of the correct type. | |||
* | |||
* @param newValue | |||
* the New value of the property. | |||
@@ -643,6 +643,7 @@ public class MethodProperty<T> extends AbstractProperty<T> { | |||
* native type directly or through <code>String</code>. | |||
* @see #invokeSetMethod(Object) | |||
*/ | |||
@SuppressWarnings("unchecked") | |||
public void setValue(Object newValue) throws Property.ReadOnlyException, | |||
Property.ConversionException { | |||
@@ -651,40 +652,14 @@ public class MethodProperty<T> extends AbstractProperty<T> { | |||
throw new Property.ReadOnlyException(); | |||
} | |||
Object value = convertValue(newValue, type); | |||
invokeSetMethod(value); | |||
fireValueChange(); | |||
} | |||
/** | |||
* Convert a value to the given type, using a constructor of the type that | |||
* takes a single String parameter (toString() for the value) if necessary. | |||
* | |||
* @param value | |||
* to convert | |||
* @param type | |||
* type into which the value should be converted | |||
* @return converted value | |||
*/ | |||
static Object convertValue(Object value, Class<?> type) { | |||
if (null == value || type.isAssignableFrom(value.getClass())) { | |||
return value; | |||
// Checks the type of the value | |||
if (newValue != null && !type.isAssignableFrom(newValue.getClass())) { | |||
throw new Property.ConversionException( | |||
"Invalid value type for ObjectProperty."); | |||
} | |||
// convert using a string constructor | |||
try { | |||
// Gets the string constructor | |||
@SuppressWarnings("rawtypes") | |||
final Constructor constr = type | |||
.getConstructor(new Class[] { String.class }); | |||
// Create a new object from the string | |||
return constr.newInstance(new Object[] { value.toString() }); | |||
} catch (final java.lang.Exception e) { | |||
throw new Property.ConversionException(e); | |||
} | |||
invokeSetMethod((T) newValue); | |||
fireValueChange(); | |||
} | |||
/** | |||
@@ -693,7 +668,7 @@ public class MethodProperty<T> extends AbstractProperty<T> { | |||
* | |||
* @param value | |||
*/ | |||
protected void invokeSetMethod(Object value) { | |||
protected void invokeSetMethod(T value) { | |||
try { | |||
// Construct a temporary argument array only if needed |
@@ -213,9 +213,13 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> { | |||
throw new Property.ReadOnlyException(); | |||
} | |||
Object value = MethodProperty.convertValue(newValue, type); | |||
// Checks the type of the value | |||
if (newValue != null && !type.isAssignableFrom(newValue.getClass())) { | |||
throw new Property.ConversionException( | |||
"Invalid value type for NestedMethodProperty."); | |||
} | |||
invokeSetMethod(value); | |||
invokeSetMethod((T) newValue); | |||
fireValueChange(); | |||
} | |||
@@ -225,7 +229,7 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> { | |||
* | |||
* @param value | |||
*/ | |||
protected void invokeSetMethod(Object value) { | |||
protected void invokeSetMethod(T value) { | |||
try { | |||
Object object = instance; | |||
for (int i = 0; i < getMethods.size() - 1; i++) { |
@@ -4,8 +4,6 @@ | |||
package com.vaadin.data.util; | |||
import java.lang.reflect.Constructor; | |||
import com.vaadin.data.Property; | |||
/** | |||
@@ -107,18 +105,19 @@ public class ObjectProperty<T> extends AbstractProperty<T> { | |||
} | |||
/** | |||
* Sets the value of the property. This method supports setting from | |||
* <code>String</code> if either <code>String</code> is directly assignable | |||
* to property type, or the type class contains a string constructor. | |||
* Sets the value of the property. | |||
* | |||
* Note that since Vaadin 7, no conversions are performed and the value must | |||
* be of the correct type. | |||
* | |||
* @param newValue | |||
* the New value of the property. | |||
* @throws <code>Property.ReadOnlyException</code> if the object is in | |||
* read-only mode | |||
* @throws <code>Property.ConversionException</code> if the newValue can't | |||
* be converted into the Property's native type directly or through | |||
* <code>String</code> | |||
* @throws <code>Property.ConversionException</code> if the newValue is not | |||
* of a correct type | |||
*/ | |||
@SuppressWarnings("unchecked") | |||
public void setValue(Object newValue) throws Property.ReadOnlyException, | |||
Property.ConversionException { | |||
@@ -127,29 +126,15 @@ public class ObjectProperty<T> extends AbstractProperty<T> { | |||
throw new Property.ReadOnlyException(); | |||
} | |||
// Tries to assign the compatible value directly | |||
if (newValue == null || type.isAssignableFrom(newValue.getClass())) { | |||
@SuppressWarnings("unchecked") | |||
// the cast is safe after an isAssignableFrom check | |||
T value = (T) newValue; | |||
this.value = value; | |||
} else { | |||
try { | |||
// Gets the string constructor | |||
final Constructor<T> constr = getType().getConstructor( | |||
new Class[] { String.class }); | |||
// Creates new object from the string | |||
value = constr | |||
.newInstance(new Object[] { newValue.toString() }); | |||
} catch (final java.lang.Exception e) { | |||
throw new Property.ConversionException(e); | |||
} | |||
// Checks the type of the value | |||
if (newValue != null && !type.isAssignableFrom(newValue.getClass())) { | |||
throw new Property.ConversionException( | |||
"Invalid value type for ObjectProperty."); | |||
} | |||
// the cast is safe after an isAssignableFrom check | |||
this.value = (T) newValue; | |||
fireValueChange(); | |||
} | |||
} |
@@ -6,7 +6,7 @@ import junit.framework.TestCase; | |||
import com.vaadin.data.util.MethodProperty; | |||
import com.vaadin.data.util.converter.Converter; | |||
import com.vaadin.data.util.converter.NumberToStringConverter; | |||
import com.vaadin.data.util.converter.IntegerToStringConverter; | |||
import com.vaadin.tests.data.bean.Address; | |||
import com.vaadin.tests.data.bean.Country; | |||
import com.vaadin.tests.data.bean.Person; | |||
@@ -22,7 +22,7 @@ public class AbstractFieldValueConversions extends TestCase { | |||
public void testWithoutConversion() { | |||
TextField tf = new TextField(); | |||
tf.setPropertyDataSource(new MethodProperty<Person>(paulaBean, | |||
tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, | |||
"firstName")); | |||
assertEquals("Paula", tf.getValue()); | |||
assertEquals("Paula", tf.getPropertyDataSource().getValue()); | |||
@@ -52,7 +52,7 @@ public class AbstractFieldValueConversions extends TestCase { | |||
return String.class; | |||
} | |||
}); | |||
tf.setPropertyDataSource(new MethodProperty<Person>(paulaBean, | |||
tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, | |||
"firstName")); | |||
assertEquals("Paula", tf.getValue()); | |||
assertEquals("Paula", tf.getPropertyDataSource().getValue()); | |||
@@ -95,8 +95,8 @@ public class AbstractFieldValueConversions extends TestCase { | |||
public void testIntegerStringConversion() { | |||
TextField tf = new TextField(); | |||
tf.setValueConverter(new NumberToStringConverter()); | |||
tf.setPropertyDataSource(new MethodProperty<Person>(paulaBean, "age")); | |||
tf.setValueConverter(new IntegerToStringConverter()); | |||
tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean, "age")); | |||
assertEquals(34, tf.getPropertyDataSource().getValue()); | |||
assertEquals("34", tf.getValue()); | |||
tf.setValue("12"); | |||
@@ -138,10 +138,10 @@ public class AbstractFieldValueConversions extends TestCase { | |||
} | |||
}); | |||
MethodProperty<Person> property = new MethodProperty<Person>(paulaBean, | |||
"deceased"); | |||
MethodProperty<Boolean> property = new MethodProperty<Boolean>( | |||
paulaBean, "deceased"); | |||
cb.setPropertyDataSource(property); | |||
assertNull(property.getValue()); | |||
assertEquals(Boolean.FALSE, property.getValue()); | |||
assertEquals(Boolean.FALSE, cb.getValue()); | |||
Boolean newDmValue = cb.getValueConverter().convertFromSourceToTarget( | |||
cb.getValue(), new Locale("fi", "FI")); |
@@ -17,12 +17,12 @@ public class DoubleInTextField extends AbstractComponentDataBindingTest { | |||
TextField salary = new TextField("Vaadin 7 - TextField with Double"); | |||
addComponent(salary); | |||
salary.setPropertyDataSource(new MethodProperty<Person>(person, | |||
salary.setPropertyDataSource(new MethodProperty<Double>(person, | |||
"salaryDouble")); | |||
TextField salary6 = new TextField("Vaadin 6 - TextField with Double"); | |||
addComponent(salary6); | |||
salary6.setPropertyDataSource(new MethodProperty<Person>(person, | |||
salary6.setPropertyDataSource(new MethodProperty<Double>(person, | |||
"salaryDouble")); | |||
salary6.setValueConverter(new Vaadin6ImplicitDoubleConverter()); | |||