summaryrefslogtreecommitdiffstats
path: root/server/src/com/vaadin/data
diff options
context:
space:
mode:
authorHenri Sara <hesara@vaadin.com>2013-02-14 12:25:27 +0000
committerVaadin Code Review <review@vaadin.com>2013-02-14 12:25:27 +0000
commitfcf06fd066a2a4df8c7b5556dd84a0acd2d4cc9f (patch)
tree49c5d52857b8e3f84320ea6494e2d08114f61b31 /server/src/com/vaadin/data
parent4a56bfb8cde78a6e17111b90aa670bf7bac562df (diff)
parent65d4fa9ccc21b1796ec5843597274459904ad5f8 (diff)
downloadvaadin-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.java36
-rw-r--r--server/src/com/vaadin/data/fieldgroup/FieldGroup.java93
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.