From 3eaee7d5d676c60641c198bd8b9352e650a6fe22 Mon Sep 17 00:00:00 2001 From: Jonni Nakari Date: Thu, 13 Dec 2012 14:41:26 +0200 Subject: [PATCH] Fix for ticket #10121, a unit test for the ticket's issue and a unit test for the new method in ReflectTools Change-Id: If8d57b4b38e8856ff2a9ef130dc71cf5b315858a --- .../vaadin/data/fieldgroup/FieldGroup.java | 2 +- server/src/com/vaadin/util/ReflectTools.java | 50 ++++++++++++++ .../fieldgroup/FieldNamedDescription.java | 53 +++++++++++++++ .../util/ReflectToolsGetFieldValueByType.java | 65 +++++++++++++++++++ .../ReflectToolsGetPrimitiveFieldValue.java | 26 ++++++++ 5 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 server/tests/src/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescription.java create mode 100644 server/tests/src/com/vaadin/util/ReflectToolsGetFieldValueByType.java create mode 100644 server/tests/src/com/vaadin/util/ReflectToolsGetPrimitiveFieldValue.java diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index 5a69cad62e..51cd3126cb 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -830,7 +830,7 @@ public class FieldGroup implements Serializable { try { // Get the field from the object field = (Field) ReflectTools.getJavaFieldValue( - objectWithMemberFields, memberField); + objectWithMemberFields, memberField, Field.class); } catch (Exception e) { // If we cannot determine the value, just skip the field and try // the next one diff --git a/server/src/com/vaadin/util/ReflectTools.java b/server/src/com/vaadin/util/ReflectTools.java index 285d876e1c..2b0b4ce29a 100644 --- a/server/src/com/vaadin/util/ReflectTools.java +++ b/server/src/com/vaadin/util/ReflectTools.java @@ -93,6 +93,56 @@ public class ReflectTools { return field.get(object); } + /** + * Returns the value of the java field that is assignable to the property + * type. + *

+ * Uses getter if a getter for the correct return type is present, otherwise + * tries to access even private fields directly. If the java field is not + * assignable to the property type throws an IllegalArgumentException. + * + * @param object + * The object containing the field + * @param field + * The field we want to get the value for + * @param propertyType + * The type the field must be assignable to + * @return The value of the field in the object + * @throws InvocationTargetException + * If the value could not be retrieved + * @throws IllegalAccessException + * If the value could not be retrieved + * @throws IllegalArgumentException + * If the value could not be retrieved + */ + public static Object getJavaFieldValue(Object object, + java.lang.reflect.Field field, Class propertyType) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { + PropertyDescriptor pd; + try { + pd = new PropertyDescriptor(field.getName(), object.getClass()); + if (propertyType.isAssignableFrom(pd.getPropertyType())) { + Method getter = pd.getReadMethod(); + if (getter != null) { + return getter.invoke(object, (Object[]) null); + } + } + } catch (IntrospectionException e1) { + // Ignore this and try to get directly using the field + } + // If the field's type cannot be casted in to the requested type + if (!propertyType.isAssignableFrom(field.getType())) { + throw new IllegalArgumentException(); + } + // Try to get the value or throw an exception + if (!field.isAccessible()) { + // Try to gain access even if field is private + field.setAccessible(true); + } + return field.get(object); + } + /** * Sets the value of a java field. *

diff --git a/server/tests/src/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescription.java b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescription.java new file mode 100644 index 0000000000..033f1458e8 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescription.java @@ -0,0 +1,53 @@ +package com.vaadin.tests.server.component.fieldgroup; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.fieldgroup.PropertyId; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.TextField; + +public class FieldNamedDescription { + + @Test + public void bindReadOnlyPropertyToFieldGroup() { + // Create an item + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("name", new ObjectProperty("Zaphod")); + item.addItemProperty("description", new ObjectProperty( + "This is a description")); + + // Define a form as a class that extends some layout + class MyForm extends FormLayout { + // Member that will bind to the "name" property + TextField name = new TextField("Name"); + + // This member will not bind to the desctiptionProperty as the name + // description conflicts with something in the binding process + @PropertyId("description") + TextField description = new TextField("Description"); + + public MyForm() { + + // Add the fields + addComponent(name); + addComponent(description); + } + } + + // Create one + MyForm form = new MyForm(); + + // Now create a binder that can also creates the fields + // using the default field factory + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue(form.description.getValue().equals("This is a description")); + } + +} diff --git a/server/tests/src/com/vaadin/util/ReflectToolsGetFieldValueByType.java b/server/tests/src/com/vaadin/util/ReflectToolsGetFieldValueByType.java new file mode 100644 index 0000000000..78be9b04fb --- /dev/null +++ b/server/tests/src/com/vaadin/util/ReflectToolsGetFieldValueByType.java @@ -0,0 +1,65 @@ +package com.vaadin.util; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.lang.reflect.InvocationTargetException; + +import org.junit.Test; + +public class ReflectToolsGetFieldValueByType { + @Test + public void getFieldValue() { + class MyClass { + public Integer getField() { + return 1; + } + + public void setField(Integer i) { + } + + } + class MySubClass extends MyClass { + public String field = "Hello"; + } + + MySubClass myInstance = new MySubClass(); + + java.lang.reflect.Field memberField; + Object fieldValue = new Boolean(false); + try { + memberField = myInstance.getClass().getField("field"); + // Should get a String value. Without the third parameter (calling + // ReflectTools.getJavaFieldValue(Object object, Field field)) would + // get an Integer value + fieldValue = ReflectTools.getJavaFieldValue(myInstance, + memberField, String.class); + } catch (Exception e) { + } + assertTrue(fieldValue instanceof String); + + } + + @Test + public void getFieldValueViaGetter() { + class MyClass { + public Integer field = 1; + } + class MySubClass extends MyClass { + public String field = "Hello"; + } + + MySubClass myInstance = new MySubClass(); + + java.lang.reflect.Field memberField; + try { + memberField = myInstance.getClass().getField("field"); + // Should throw an IllegalArgument exception as the mySubClass class + // doesn't have an Integer field. + ReflectTools.getJavaFieldValue(myInstance, + memberField, Integer.class); + fail("Previous method call should have thrown an exception"); + } catch (Exception e) { + } + } +} \ No newline at end of file diff --git a/server/tests/src/com/vaadin/util/ReflectToolsGetPrimitiveFieldValue.java b/server/tests/src/com/vaadin/util/ReflectToolsGetPrimitiveFieldValue.java new file mode 100644 index 0000000000..df192c51f2 --- /dev/null +++ b/server/tests/src/com/vaadin/util/ReflectToolsGetPrimitiveFieldValue.java @@ -0,0 +1,26 @@ +package com.vaadin.util; + +import static org.junit.Assert.assertFalse; + +import org.junit.Test; + +public class ReflectToolsGetPrimitiveFieldValue { + @Test + public void getFieldValueViaGetter() { + class MyClass { + public int field = 1; + } + + MyClass myInstance = new MyClass(); + + java.lang.reflect.Field memberField; + Object fieldValue = new Boolean(false); + try { + memberField = myInstance.getClass().getField("field"); + fieldValue = ReflectTools.getJavaFieldValue(myInstance, + memberField); + } catch (Exception e) { + } + assertFalse(fieldValue instanceof Boolean); + } +} \ No newline at end of file -- 2.39.5