diff options
author | Henri Sara <hesara@vaadin.com> | 2013-02-14 12:25:27 +0000 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2013-02-14 12:25:27 +0000 |
commit | fcf06fd066a2a4df8c7b5556dd84a0acd2d4cc9f (patch) | |
tree | 49c5d52857b8e3f84320ea6494e2d08114f61b31 /server/src/com/vaadin/data | |
parent | 4a56bfb8cde78a6e17111b90aa670bf7bac562df (diff) | |
parent | 65d4fa9ccc21b1796ec5843597274459904ad5f8 (diff) | |
download | vaadin-framework-fcf06fd066a2a4df8c7b5556dd84a0acd2d4cc9f.tar.gz vaadin-framework-fcf06fd066a2a4df8c7b5556dd84a0acd2d4cc9f.zip |
Merge "Case-insensitive FieldGroup binding #10426"
Diffstat (limited to 'server/src/com/vaadin/data')
-rw-r--r-- | server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java | 36 | ||||
-rw-r--r-- | server/src/com/vaadin/data/fieldgroup/FieldGroup.java | 93 |
2 files changed, 116 insertions, 13 deletions
diff --git a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java index 7e44c26c9e..c748bd6c44 100644 --- a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java @@ -58,6 +58,22 @@ public class BeanFieldGroup<T> extends FieldGroup { } } + @Override + protected Object findPropertyId(java.lang.reflect.Field memberField) { + String fieldName = memberField.getName(); + Item dataSource = getItemDataSource(); + if (dataSource != null && dataSource.getItemProperty(fieldName) != null) { + return fieldName; + } else { + String minifiedFieldName = minifyFieldName(fieldName); + try { + return getFieldName(beanType, minifiedFieldName); + } catch (SecurityException | NoSuchFieldException e) { + } + } + return null; + } + private static java.lang.reflect.Field getField(Class<?> cls, String propertyId) throws SecurityException, NoSuchFieldException { if (propertyId.contains(".")) { @@ -75,7 +91,7 @@ public class BeanFieldGroup<T> extends FieldGroup { } catch (NoSuchFieldError e) { // Try super classes until we reach Object Class<?> superClass = cls.getSuperclass(); - if (superClass != Object.class) { + if (superClass != null && superClass != Object.class) { return getField(superClass, propertyId); } else { throw e; @@ -84,6 +100,22 @@ public class BeanFieldGroup<T> extends FieldGroup { } } + private static String getFieldName(Class<?> cls, String propertyId) + throws SecurityException, NoSuchFieldException { + for (java.lang.reflect.Field field1 : cls.getDeclaredFields()) { + if (propertyId.equals(minifyFieldName(field1.getName()))) { + return field1.getName(); + } + } + // Try super classes until we reach Object + Class<?> superClass = cls.getSuperclass(); + if (superClass != null && superClass != Object.class) { + return getFieldName(superClass, propertyId); + } else { + throw new NoSuchFieldException(); + } + } + /** * Helper method for setting the data source directly using a bean. This * method wraps the bean in a {@link BeanItem} and calls @@ -166,4 +198,4 @@ public class BeanFieldGroup<T> extends FieldGroup { } return beanValidationImplementationAvailable; } -}
\ No newline at end of file +} diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index dc1fdbb78d..6c515dbdee 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -733,11 +733,12 @@ public class FieldGroup implements Serializable { * that have not been initialized. * <p> * This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property id - * mapping is done based on the field name or on a @{@link PropertyId} - * annotation on the field. Fields that are not initialized (null) are built - * using the field factory. All non-null fields for which a property id can - * be determined are bound to the property id. + * {@link Field} and that can be mapped to a property id. Property ids are + * searched in the following order: @{@link PropertyId} annotations, exact + * field name matches and the case-insensitive matching that ignores + * underscores. Fields that are not initialized (null) are built using the + * field factory. All non-null fields for which a property id can be + * determined are bound to the property id. * </p> * <p> * For example: @@ -777,11 +778,12 @@ public class FieldGroup implements Serializable { * member fields that have not been initialized. * <p> * This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property id - * mapping is done based on the field name or on a @{@link PropertyId} - * annotation on the field. Fields that are not initialized (null) are built - * using the field factory is buildFields is true. All non-null fields for - * which a property id can be determined are bound to the property id. + * {@link Field} and that can be mapped to a property id. Property ids are + * searched in the following order: @{@link PropertyId} annotations, exact + * field name matches and the case-insensitive matching that ignores + * underscores. Fields that are not initialized (null) are built using the + * field factory is buildFields is true. All non-null fields for which a + * property id can be determined are bound to the property id. * </p> * * @param objectWithMemberFields @@ -812,7 +814,16 @@ public class FieldGroup implements Serializable { // @PropertyId(propertyId) always overrides property id propertyId = propertyIdAnnotation.value(); } else { - propertyId = memberField.getName(); + try { + propertyId = findPropertyId(memberField); + } catch (SearchException e) { + // Property id was not found, skip this field + continue; + } + if (propertyId == null) { + // Property id was not found, skip this field + continue; + } } // Ensure that the property id exists @@ -873,6 +884,54 @@ public class FieldGroup implements Serializable { } } + /** + * Searches for a property id from the current itemDataSource that matches + * the given memberField. + * <p> + * If perfect match is not found, uses a case insensitive search that also + * ignores underscores. Returns null if no match is found. Throws a + * SearchException if no item data source has been set. + * </p> + * <p> + * The propertyId search logic used by + * {@link #buildAndBindMemberFields(Object, boolean) + * buildAndBindMemberFields} can easily be customized by overriding this + * method. No other changes are needed. + * </p> + * + * @param memberField + * The field an object id is searched for + * @return + */ + protected Object findPropertyId(java.lang.reflect.Field memberField) { + String fieldName = memberField.getName(); + if (getItemDataSource() == null) { + throw new SearchException( + "Property id type for field '" + + fieldName + + "' could not be determined. No item data source has been set."); + } + Item dataSource = getItemDataSource(); + if (dataSource.getItemProperty(fieldName) != null) { + return fieldName; + } else { + String minifiedFieldName = minifyFieldName(fieldName); + for (Object itemPropertyId : dataSource.getItemPropertyIds()) { + if (itemPropertyId instanceof String) { + String itemPropertyName = (String) itemPropertyId; + if (minifiedFieldName.equals(minifyFieldName(itemPropertyName))) { + return itemPropertyName; + } + } + } + } + return null; + } + + protected static String minifyFieldName(String fieldName) { + return fieldName.toLowerCase().replace("_", ""); + } + public static class CommitException extends Exception { public CommitException() { @@ -909,6 +968,18 @@ public class FieldGroup implements Serializable { } + public static class SearchException extends RuntimeException { + + public SearchException(String message) { + super(message); + } + + public SearchException(String message, Throwable t) { + super(message, t); + } + + } + /** * Builds a field and binds it to the given property id using the field * binder. |