* Changed retrieval of names of nested properties (#10159) The getName() function in NestedBeanPropertyDefinition will return only the top level name, which causes problems when adding a nested property that has the same name as a non-nested (e.g "value" & "sub.value") This change should fix this behaviour by changing the return value of "getName()" of NestedBeanPropertyDefinition and introducing a function "getTopLevelName()" that only returns the last part of the full name for where it's neededtags/8.3.0.alpha1
@@ -170,37 +170,13 @@ public class BeanPropertySet<T> implements PropertySet<T> { | |||
private final PropertyDefinition<T, ?> parent; | |||
private boolean useLongFormName = false; | |||
public NestedBeanPropertyDefinition(BeanPropertySet<T> propertySet, | |||
PropertyDefinition<T, ?> parent, | |||
PropertyDescriptor descriptor) { | |||
super(propertySet, parent.getType(), descriptor); | |||
this.parent = parent; | |||
} | |||
/** | |||
* Create nested property definition. Allows use of a long form name. | |||
* | |||
* @param propertySet | |||
* property set this property belongs to | |||
* @param parent | |||
* parent property for this nested property | |||
* @param descriptor | |||
* property descriptor | |||
* @param useLongFormName | |||
* use format grandparent.parent.property for name if | |||
* {@code true}, needed when creating nested definitions | |||
* recursively like in findNestedDefinitions | |||
* @since 8.2 | |||
*/ | |||
public NestedBeanPropertyDefinition(BeanPropertySet<T> propertySet, | |||
PropertyDefinition<T, ?> parent, PropertyDescriptor descriptor, | |||
boolean useLongFormName) { | |||
this(propertySet, parent, descriptor); | |||
this.useLongFormName = useLongFormName; | |||
} | |||
@Override | |||
public ValueProvider<T, V> getGetter() { | |||
return bean -> { | |||
@@ -229,6 +205,16 @@ public class BeanPropertySet<T> implements PropertySet<T> { | |||
return Optional.of(setter); | |||
} | |||
@Override | |||
public String getName() { | |||
return parent.getName() + "." + super.getName(); | |||
} | |||
@Override | |||
public String getTopLevelName() { | |||
return super.getName(); | |||
} | |||
private Object writeReplace() { | |||
/* | |||
* Instead of serializing this actual property definition, only | |||
@@ -236,8 +222,9 @@ public class BeanPropertySet<T> implements PropertySet<T> { | |||
* property definition from the cache. | |||
*/ | |||
return new SerializedPropertyDefinition(getPropertySet().beanType, | |||
parent.getName() + "." + super.getName()); | |||
getName()); | |||
} | |||
/** | |||
* Gets the parent property definition. | |||
@@ -247,15 +234,6 @@ public class BeanPropertySet<T> implements PropertySet<T> { | |||
public PropertyDefinition<T, ?> getParent() { | |||
return parent; | |||
} | |||
@Override | |||
public String getName() { | |||
if (useLongFormName) { | |||
return parent.getName() + "." + super.getName(); | |||
} | |||
return super.getName(); | |||
} | |||
} | |||
/** | |||
@@ -394,7 +372,7 @@ public class BeanPropertySet<T> implements PropertySet<T> { | |||
PropertyDescriptor subDescriptor = BeanUtil | |||
.getPropertyDescriptor(beanType, name); | |||
moreProps.put(name, new NestedBeanPropertyDefinition<>(this, | |||
parentProperty, subDescriptor, true)); | |||
parentProperty, subDescriptor)); | |||
} | |||
} catch (IntrospectionException e) { |
@@ -96,7 +96,7 @@ public class BeanValidationBinder<BEAN> extends Binder<BEAN> { | |||
PropertyDefinition<BEAN, ?> definition) { | |||
Class<?> actualBeanType = findBeanType(beanType, definition); | |||
BeanValidator validator = new BeanValidator(actualBeanType, | |||
definition.getName()); | |||
definition.getTopLevelName()); | |||
if (requiredConfigurator != null) { | |||
configureRequired(binding, definition, validator); | |||
} | |||
@@ -132,7 +132,7 @@ public class BeanValidationBinder<BEAN> extends Binder<BEAN> { | |||
BeanDescriptor descriptor = validator.getJavaxBeanValidator() | |||
.getConstraintsForClass(propertyHolderType); | |||
PropertyDescriptor propertyDescriptor = descriptor | |||
.getConstraintsForProperty(definition.getName()); | |||
.getConstraintsForProperty(definition.getTopLevelName()); | |||
if (propertyDescriptor == null) { | |||
return; | |||
} |
@@ -64,12 +64,19 @@ public interface PropertyDefinition<T, V> extends Serializable { | |||
public Class<?> getPropertyHolderType(); | |||
/** | |||
* Gets the name of this property. | |||
* Gets the full name of this property. | |||
* | |||
* @return the property name, not <code>null</code> | |||
*/ | |||
public String getName(); | |||
/** | |||
* Gets the top level name of this property | |||
* | |||
* @return the top level property name, not <code>null</code> | |||
*/ | |||
public default String getTopLevelName() {return getName();} | |||
/** | |||
* Gets the human readable caption to show for this property. | |||
* |
@@ -0,0 +1,48 @@ | |||
package com.vaadin.data; | |||
import org.junit.Test; | |||
import com.vaadin.ui.Grid; | |||
public class NestedPropertyNameTest { | |||
@Test | |||
public void nestedProperty_sameNameCanBeAdded() { | |||
Grid<Person> grid = new Grid<>(Person.class); | |||
grid.addColumn("street.name"); | |||
} | |||
private class Person{ | |||
String name; | |||
Street street; | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
public Street getStreet() { | |||
return street; | |||
} | |||
public void setStreet(Street street) { | |||
this.street = street; | |||
} | |||
} | |||
private class Street{ | |||
String name; | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
} | |||
} |